Chrome DevTools

Must Watch!



MustWatch



Overview

Chrome DevTools is a set of web developer tools built directly into the Google Chrome browser. DevTools can help you edit pages on-the-fly and diagnose problems quickly, which ultimately helps you build better websites, faster. Check out the video for live demonstrations of core DevTools workflows, including debugging CSS, prototyping CSS, debugging JavaScript, and analyzing load performance.

Open DevTools

There are many ways to open DevTools, because different users want quick access to different parts of the DevTools UI. When you want to work with the DOM or CSS, right-click an element on the page and select Inspect to jump into the Elements panel. Or press Command+Option+C (Mac) or Control+Shift+C (Windows, Linux, Chrome OS). When you want to see logged messages or run JavaScript, press Command+Option+J (Mac) or Control+Shift+J (Windows, Linux, Chrome OS) to jump straight into the Console panel. See Open Chrome DevTools for more details and workflows.

Get started

If you're a more experienced web developer, here are the recommended starting points for learning how DevTools can improve your productivity: View and Change the DOM View and Change a Page's Styles (CSS) Debug JavaScript View Messages and Run JavaScript in the Console Optimize Website Speed Inspect Network Activity

Discover DevTools

The DevTools UI can be a little overwhelming... there are so many tabs! But, if you take some time to get familiar with each tab to understand what's possible, you may discover that DevTools can seriously boost your productivity. Note: In the DevTools docs, the top-level tabs are called panels.

 Device Mode

Simulate mobile devices. Device Mode Test Responsive and Device-specific Viewports Emulate Sensors: Geolocation & Accelerometer

 Elements panel

View and change the DOM and CSS. Get Started With Viewing And Changing The DOM Get Started With Viewing And Changing CSS Inspect and Tweak Your Pages Edit Styles Edit the DOM Inspect Animations Find Unused CSS

 Console panel

View messages and run JavaScript from the Console. Get Started With The Console Using the Console Interact from Command Line Console API Reference

 Sources panel

Debug JavaScript, persist changes made in DevTools across page reloads, save and run snippets of JavaScript, and save changes that you make in DevTools to disk. Debugging JavaScript Pause Your Code With Breakpoints Save Changes to Disk with Workspaces Run Snippets of JavaScript JavaScript Debugging Reference Persist Changes Across Page Reloads with Local Overrides Find Unused JavaScript

 Network panel

View and debug network activity. Get Started Network Issues Guide Network Panel Reference Inspect Resources

 Performance panel

Note: In Chrome 58 the Timeline panel was renamed to the Performance panel. Find ways to improve load and runtime performance. Optimize Website Speed Get Started With Analyzing Runtime Performance Performance Analysis Reference Analyze runtime performance Diagnose Forced Synchronous Layouts

 Memory panel

Note: In Chrome 58 the Profiles panel was renamed to the Memory panel. Fix Memory Problems JavaScript CPU Profiler

 Application panel

Inspect all resources that are loaded, including IndexedDB or Web SQL databases, local and session storage, cookies, Application Cache, images, fonts, and stylesheets. Debug Progressive Web Apps Inspect and Manage Storage, Databases, and Caches Inspect and Delete Cookies

 Security panel

Debug mixed content issues, certificate problems, and more. Understand Security Issues

Community

File bug reports and feature requests in Crbug, which is the engineering team's bug tracker. Crbug If you want to alert us to a bug or feature request but don't have much time, you're welcome to send a tweet to @ChromeDevTools. We reply and send announcements from the account regularly. Twitter For help with using DevTools, Stack Overflow is the best channel. Stack Overflow To file bugs or feature requests on the DevTools docs, open a GitHub issue on the Web Fundamentals repository. Docs Issues DevTools also has a Slack channel, but the team doesn't monitor it consistently. Slack Improve article


Open Chrome DevTools

There are many ways to open Chrome DevTools, because different users want fast access to different parts of the DevTools UI.

Open the Elements panel to inspect the DOM or CSS

When you want to inspect a DOM node's styles or attributes, right-click the element and select Inspect. Figure 1. The Inspect option Or press Command+Option+C (Mac) or Control+Shift+C (Windows, Linux, Chrome OS). See Get Started With Viewing And Changing CSS.

Open the Console panel to view logged messages or run JavaScript

Press Command+Option+J (Mac) or Control+Shift+J (Windows, Linux, Chrome OS) to jump straight into the Console panel. See Get Started With The Console.

Open the last panel you had open

Press Command+Option+I (Mac) or Control+Shift+I.

Open DevTools from Chrome's main menu

Click Customize and control Google Chrome and then select More Tools > Developer Tools. Figure 2. Opening DevTools from Chrome's main menu

Auto-open DevTools on every new tab

Open Chrome from the Command line and pass the --auto-open-devtools-for-tabs flag. Mac: /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --auto-open-devtools-for-tabs This will only work if an instance of Chrome is not already running. From then on, every new tab will automatically open DevTools until the user fully quits Chrome. Improve article


View and change CSS

Complete these interactive tutorials to learn the basics of viewing and changing a page's CSS using Chrome DevTools.

View an element's CSS

Right-click the Inspect Me! text below and select Inspect. The Elements panel of DevTools opens. The Inspect Me! element is highlighted in the DOM Tree. Inspect Me! In the DOM Tree, find the value of the data-message attribute for the Inspect Me! element. Enter the value in the text box below. The Styles tab on the Elements panel lists the CSS rules being applied to whatever element is currently selected in the DOM Tree, which should still be the Inspect Me! element in this case. Find the aloha class rule. The fact that you see this rule means that it's being applied to the Inspect Me! element. The aloha class is declaring a value for padding. Enter that value in the text box below. Figure 1. The inspected element is highlighted blue in the DOM Tree If you'd like to dock your DevTools window to the right of your viewport, like you see in Figure 1, see Change DevTools placement. Figure 2. CSS classes being applied to the selected element, such as aloha, are displayed in the Styles tab

Add a CSS declaration to an element

Use the Styles tab when you want to change or add CSS declarations to an element. Right-click the Add A Background Color To Me! text below and select Inspect. Add A Background Color To Me! Click element.style near the top of the Styles tab. Type background-color and press Enter. Type honeydew and press Enter. In the DOM Tree you can see that an inline style declaration was applied to the element. Figure 3. The background-color:honeydew declaration has been applied to the element via the element.style section of the Styles tab

Add a CSS class to an element

Use the Styles tab to see how an element looks when a CSS class is applied to or removed from an element. Right-click the Add A Class To Me! element below and select Inspect. Add A Class To Me! Click .cls. DevTools reveals a text box where you can add classes to the selected element. Type color_me in the Add new class text box and then press Enter. A checkbox appears below the Add new class text box, where you can toggle the class on and off. If the Add A Class To Me! element had any other classes applied to it, you'd also be able to toggle them from here. Figure 4. The color_me class has been applied to the element via the .cls section of the Styles tab

Add a pseudostate to a class

Use the Styles tab to permanently apply a CSS pseudostate to an element. DevTools supports :active, :focus, :hover, :visited, and others. Hover over the Hover Over Me! text below. The background color changes. Hover Over Me! Right-click the Hover Over Me! text and select Inspect. In the Styles tab, click :hov. Check the :hover checkbox. The background color changes like before, even though you're not actually hovering over the element. Figure 5. Toggling the :hover pseudostate on an element

Change the dimensions of an element

Use the Box Model interactive diagram in the Styles tab to change the width, height, padding, margin, or border length of an element. Right-click the Change My Margin! element below and select Inspect. Change My Margin! In the Box Model diagram in the Styles tab, hover over padding. The element's padding is highlighted in the viewport. Note: Depending on the size of your DevTools window, you may need to scroll to the bottom of the Styles tab to see the Box Model. Double-click the left margin in the Box Model, which currently has a value of - meaning that the element doesn't have a left-margin. Type 100 and press Enter. The Box Model defaults to pixels, but it also accepts other values, such as 25%, or 10vw. Figure 6. Hovering over the element's padding Figure 7. Changing the element's left-margin Improve article


CSS features reference

Discover new workflows in this comprehensive reference of Chrome DevTools features related to viewing and changing CSS. See Get Started with Viewing and Changing CSS to learn the basics.

Select an element

The Elements panel of DevTools lets you view or change the CSS of one element at a time. The selected element is highlighted blue in the DOM Tree. The element's styles are shown in the Styles pane. See View an element's CSS for a tutorial. Figure 1. The h1 element that's highlighted blue in the DOM Tree is the selected element. To the right, the element's styles are shown in the Styles pane. To the left, the element is highlighted in the viewport, but only because the mouse is currently hovering over it in the DOM Tree There are many ways to select an element: In your viewport, right-click the element and select Inspect. In DevTools, click Select an element or press Command+Shift+C (Mac) or Control+Shift+C (Windows, Linux), and then click the element in the viewport. In DevTools, click the element in the DOM Tree. In DevTools, run a query like document.querySelector('p') in the Console, right-click the result, and then select Reveal in Elements panel.

View CSS

 View the external stylesheet where a rule is defined

In the Styles pane, click the link next to a CSS rule to open the external stylesheet that defines the rule. If the stylesheet is minified, see Make a minified file readable. Figure 2. Clicking devsite-google-blue.css:487 takes you to line 487 of devsite-google-blue.css, where the .devsite-article h1:first-of-type CSS rule is defined.

 View only the CSS that's actually applied to an element

The Styles tab shows you all of the rules that apply to an element, including declarations that have been overridden. When you're not interested in overridden declarations, use the Computed tab to view only the CSS that's actually being applied to an element. Select an element. Go to the Computed tab in the Elements panel. Note: On a wide DevTools window, the Computed tab does not exist. The contents of the Computed tab are shown on the Styles tab. Inherited properties are opaque. Check the Show All checkbox to see all inherited values. Figure 3. The Computed tab shows the CSS properties being applied to the currently-selected h1 element

 View CSS properties in alphabetical order

Use the Computed tab. See View only the CSS that's actually applied to an element.

 View inherited CSS properties

Check the Show All checkbox in the Computed tab. See View only the CSS that's actually applied to an element.

 View an element's box model

To view the box model of an element, go to the Styles tab. If your DevTools window is narrow, the Box Model diagram is at the bottom of the tab. To change a value, double-click on it. Figure 4. The Box Model diagram in the Styles tab shows the box model for the currently selected h1 element

 Search and filter an element's CSS

Use the Filter text box on the Styles and Computed tabs to search for specific CSS properties or values. To also search inherited properties in the Computed tab, check the Show All checkbox. Figure 5. Filtering the Styles tab to only show rules that include the search query color Figure 6. Filtering the Computed tab to only show declarations that include the search query 100%

 Toggle a pseudo-class

To toggle a pseudo-class like :active, :focus, :hover, :visited, :focus-within or focus-visible: Select an element. On the Elements panel, go to the Styles tab. Click :hov. Check the pseudo-class that you want to enable. Figure 7. Toggling the :hover pseudo-class. In the viewport you can see that the background-color: cornflowerblue declaration is being applied to the element, even though the element is not actually being hovered over See Add a pseudostate to a class for an interactive tutorial.

 View a page in print mode

To view a page in print mode: Open the Command Menu. Start typing Rendering and select Show Rendering. For the Emulate CSS Media dropdown, select print.

 View used and unused CSS with the Coverage tab

The Coverage tab shows you what CSS a page actually uses. Press Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux, Chrome OS) while DevTools is in focus to open the Command Menu. Start typing coverage and select Show Coverage. The Coverage tab appears. Figure 8. Opening the Coverage tab from the Command Menu Figure 9. The Coverage tab Click Start Instrumenting Coverage And Reload Page . The page reloads and the Coverage tab provides an overview of how much CSS (and JavaScript) is used from each file that the browser loads. Green represents used CSS. Red represents unused CSS. Figure 10. An overview of how much CSS (and JavaScript) is used and unused Click a CSS file to see a line-by-line breakdown of what CSS it uses. Figure 11. Lines 55 to 57 and 65 to 67 of devsite-google-blue.css are unused, whereas lines 59 to 63 are used

 Force print preview mode

See Force DevTools Into Print Preview Mode.

Change CSS

 Add a CSS declaration to an element

Since the order of declarations affects how an element is styled, you can add declarations in different ways: Add a inline declaration. Equivalent to adding a style attribute to the element's HTML. Add a declaration to a style rule. What workflow should you use? For most scenarios, you probably want to use the inline declaration workflow. Inline declarations have higher specificity than external ones, so the inline workflow ensures that the changes take effect in the element as you'd expect. See Selector Types for more on specificity. If you're debugging an element's styles and you need to specifically test what happens when a declaration is defined in different places, use the other workflow.

Add an inline declaration

To add an inline declaration: Select an element. In the Styles pane, click between the brackets of the element.style section. The cursor focuses, allowing you to enter text. Enter a property name and press Enter. Enter a valid value for that property and press Enter. In the DOM Tree, you can see that a style attribute has been added to the element. Figure 12. The margin-top and background-color properties have been applied to the selected element. In the DOM Tree you can see the declarations reflected in the element's style attribute

Add a declaration to a style rule

To add a declaration to an existing style rule: Select an element. In the Styles pane, click between the brackets of the style rule to which you want to add the declaration. The cursor focuses, allowing you to enter text. Enter a property name and press Enter. Enter a valid value for that property and press Enter. Figure 13. Adding the border-bottom-style:groove declaration to a style rule

 Change a declaration name or value

Double-click a declaration's name or value to change it. See Change declaration values with keyboard shortcuts for shortcuts for quickly incrementing or decrementing a value by 0.1, 1, 10, or 100 units.

 Change declaration values with keyboard shortcuts

While editing the value of a declaration, you can use the following keyboard shortcuts to increment the value by a fixed amount: Option+Up (Mac) or Alt+Up (Windows, Linux) to increment by 0.1. Up to change the value by 1, or by 0.1 if the current value is between -1 and 1. Shift+Up to increment by 10. Shift+Command+Up (Mac) or Shift+Page Up (Windows, Linux) to increment the value by 100. Decrementing also works. Just replace each instance of Up mentioned above with Down.

 Add a class to an element

To add a class to an element: Select the element in the DOM Tree. Click .cls. Enter the name of the class in the Add New Class text box. Press Enter. Figure 14. The Element Classes pane

 Toggle a class

To enable or disable a class on an element: Select the element in the DOM Tree. Open the Element Classes pane. See Add a class to an element. Below the Add New Class text box are all of the classes that are being applied to this element. Toggle the checkbox next to the class that you want to enable or disable.

 Add a style rule

To add a new style rule: Select an element. Click New Style Rule . DevTools inserts a new rule beneath the element.style rule. Figure 15. DevTools adds the h1.devsite-page-title style rule after clicking New Style Rule

Choose which stylesheet to add a rule to

When adding a new style rule, click and hold New Style Rule New Style Rule to choose which stylesheet to add the style rule to. Figure 16. Choosing a stylesheet

 Toggle a declaration

To toggle a single declaration on or off: Select an element. In the Styles pane, hover over the rule that defines the declaration. Checkboxes appear next to each declaration. Check or uncheck the checkbox next to the declaration. When you uncheck a declaration, DevTools crosses it out to indicate that it's no longer active. Figure 20. The color property for the currently-selected element has been toggled off

 Change colors with the Color Picker

The Color Picker provides a GUI for changing color and background-color declarations. To open the Color Picker: Select an element. In the Styles tab, find the color or background-color declaration that you want to change. To the left of the color or background-color value, there is a small square which is a preview of the color. Figure 24. The small blue square to the left of rgb(123, 170, 247) is a preview of that color Click the preview to open the Color Picker. Figure 25. The Color Picker Here's a description of each of the UI elements of the Color Picker: Figure 26. The Color Picker, annotated Shades. Eyedropper. See Sample a color off the page with the Eyedropper. Copy To Clipboard. Copy the Display Value to your clipboard. Display Value. The RGBA, HSLA, or Hex representation of the color. Color Palette. Click one of these squares to change the color to that square. Hue. Opacity. Display Value Switcher. Toggle between the RGBA, HSLA, and Hex representations of the current color. Color Palette Switcher. Toggle between the Material Design palette, a custom palette, or a page colors palette. DevTools generates the page color palette based on the colors that it finds in your stylesheets.

Sample a color off the page with the Eyedropper

When you open the Color Picker, the Eyedropper is on by default. To change the selected color to some other color on the page: Hover over the target color in the viewport. Click to confirm. Figure 27. The Color Picker shows a current color value of #212121, which is close to black. This color would change to the blue that's currently highlighted in the viewport once the blue was clicked

 Change angle value with the Angle Clock

The Angle Clock provides a GUI for changing <angle>s in CSS property values. To open the Angle Clock: Select an element with angle declaration. For example, select the text below. In the Styles tab, find the transform or background declaration that you want to change. Click on the Angle Preview box next to the angle value. Figure 28. The small clock to the left of -5deg and 0.25turn are preview of the angle. Click the preview to open the Angle Clock. Figure 29. The Angle Clock. Change the angle value by clicking on the Angle Clock circle or scroll your mouse to increase / decrease the angle value by 1. There are more keyboard shortcuts to change the angle value. Find out more in the Styles pane keyboard shortcuts. Improve article


Identify potential CSS improvements

Use the CSS Overview panel to better understand your page’s CSS and identify potential improvements. This is a preview feature in Chrome 96. Our team is actively working on this feature and we are looking for your feedback for further enhancements.

Open the CSS Overview panel

Open any web page, such as this page. Open DevTools. Click on More options > More tools > CSS Overview. Command Menu to open the CSS Overview panel.

Run and re-run a CSS Overview report

Click on the Capture overview button to generate a CSS Overview report of your page. To re-run a CSS Overview, click on the clear overview icon, and repeat step 1.

Understand the CSS Overview report

The report consists of 5 sections:- Overview summary. A high level summary of your page's CSS. Colors. All the colors in your page. The colors are grouped by usages such as background colors, text colors, etc. It also shows you the texts that have low contrast issues. Each of the color is clickable. For example, say this border color #DADCE0 doesn’t match the color scheme of your site, click on it to get a list of elements that use the color. Hover over an element in the list to highlight the element in the page. Click on the element in the list to open the element in the Elements panel. Font info. All the fonts in your page and its occurrences, grouped by different font size, font weight and line height. Similar to the Colors section, you can click on the occurrences to view the list of affected elements. Unused declarations. All the styles which have no effect, grouped by reason. For example, the 2 declarations above are unused because the height and width of an inline element are determined by its content. Clicking the occurrences to view the affected elements. Media queries. All the media queries defined in your page, sorted by the highest occurrences. Click on the occurrences to view the list of affected elements. Improve article


Inspect animations

Inspect and modify animations with the Chrome DevTools Animation Inspector.

Summary

Capture animations by opening the Animation Inspector. It automatically detects animations and sorts them into groups. Inspect animations by slowing them down, replaying them, or viewing their source code. Modify animations by changing their timing, delay, duration, or keyframe offsets.

Overview

The Chrome DevTools Animation Inspector has two main purposes. Inspecting animations. You want to slow down, replay, or inspect the source code for an animation group. Modifying animations. You want to modify the timing, delay, duration, or keyframe offsets of an animation group. Bezier editing and keyframe editing are currently not supported. The Animation Inspector supports CSS animations, CSS transitions, and web animations. requestAnimationFrame animations are currently not supported.

 What's an animation group?

An animation group is a group of animations that appear to be related to each other. Currently, the web has no real concept of a group animation, so motion designers and developers have to compose and time individual animations so that they appear to be one coherent visual effect. The Animation Inspector predicts which animations are related based on start time (excluding delays, and so on) and groups them all side-by-side. In other words, a set of animations all triggered in the same script block are grouped together, but if they're asynchronous then they're grouped separately.

Get started

There are two ways to open the Animation Inspector: Through the Main Menu: Click More to open the Main Menu. Navigate to the More tools sub-menu. Select Animations:
Open the Command Menu and type Show Animations. The Animation Inspector opens up as a tab next to the Console Drawer. Since it's a Drawer tab, you can use it from any DevTools panel. The Animation Inspector is grouped into four main sections (or panes). This guide refers to each pane as follows: Controls. From here you can clear all currently captured Animation Groups, or change the speed of the currently selected Animation Group. Overview. Select an Animation Group here to inspect and modify it in the Details pane. Timeline. Pause and start an animation from here, or jump to a specific point in the animation. Details. Inspect and modify the currently selected Animation Group. To capture an animation, just perform the interaction that triggers the animation while the Animation Inspector is open. If an animation is triggered on page load, you can help the Animation Inspector detect the animation by reloading the page.

Inspect animations

Once you've captured an animation, there are a few ways to replay it: Hover over its thumbnail in the Overview pane to view a preview of it. Select the Animation Group from the Overview pane (so that it's displayed in the Details pane) and press the replay button ( to change the preview speed of the currently selected Animation Group. You can use the red vertical bar to change your current position. Click and drag the red vertical bar to scrub the viewport animation.

 View animation details

Once you've captured an Animation Group, click on it from the Overview pane to view its details. In the Details pane each individual animation gets its own row. Hover over an animation to highlight it in the viewport. Click on the animation to select it in the Elements panel. The leftmost, darker section of an animation is its definition. The right, more faded section represents iterations. For example, in the screenshot below, sections two and three represent iterations of section one. If two elements have the same animation applied to them, the Animation Inspector assigns them the same color. The color itself is random and has no significance. For example, in the screenshot below the two elements div.eye.left::after and div.eye.right::after have the same animation (eyes) applied to them, as do the div.feet::before and div.feet::after elements.

Modify animations

There are three ways you can modify an animation with the Animation Inspector: Animation duration. Keyframe timings. Start time delay. For this section suppose that the screenshot below represents the original animation: To change the duration of an animation, click and drag the first or last circle. If the animation defines any keyframe rules, then these are represented as white inner circles. Click and drag one of these to change the timing of the keyframe. To add a delay to an animation, click and drag it anywhere except the circles. Improve article


Inspect CSS Grid

This guide shows you how to discover CSS grids on a page, examining them and debugging layout issues in the Elements panel of Chrome DevTools. The examples shown in the screenshots appearing in this article are from these two web pages: Fruit box and Snack box.

Discover CSS grids

When an HTML element on your page has display: grid or display: inline-grid applied to it, you can see a grid badge next to it in the Elements panel. Clicking the badge to toggle the display of a grid overlay on the page. The overlay appears over the element, laid out like a grid to show the position of its grid lines and tracks: Open the Layout pane. When grids are included on a page, the Layout pane includes a Grid section containing a number of options for viewing those grids.

Grid viewing options

The Grid section in the Layout pane contains 2 sub sections: Overlay display settings Grid overlays Let's look into each of these sub sections in detail.

Overlay display settings

The Overlay display settings consists of 2 parts: a. A dropdown menu with options within: Hide line labels: Hide the line labels for each grid overlay. Show lines number: Show the line numbers for each grid overlay (selected by default). Show line names: Show the line names for each grid overlay in the case of grids with line names. b. Checkboxes with options within: Show track sizes: Toggle to show or hide track sizes. Show area names: Toggle to show or hide area names, in the case of grids with named grid areas. Extend grid lines: By default, grid lines are only shown inside the element with display: grid or display: inline-grid set on it; when toggling this option on, the grid lines extend to the edge of the viewport along each axis. Let's examine these settings in more detail.

 Show line numbers

By default, the positive and negative line numbers are displayed on the grid overlay.

 Hide line labels

Select Hide line labels to hide the line numbers.

 Show line names

You can select Show line names to view the line names instead of numbers. In this example, we have 4 lines with names: left, middle1, middle2 and right. In this demo, orange element spans from left to right, with CSS grid-column: left / right. Showing line names make it easier to visualize the start and end position of the element.

 Show track sizes

Enable the Show track sizes checkbox to view the track sizes of the grid. DevTools will display [authored size] - [computed size] in each line label: Authored size: The size defined in stylesheet (omitted if not defined). Computed size: The actual size on screen. In this demo, the snack-box column sizes are defined in the CSS grid-template-columns:1fr 2fr;. Therefore, the column line labels show both authored and computed sizes: 1fr - 96.66px and 2fr - 193.32px. The row line labels show only computed sizes: 80px and 80px since there are no row sizes defined in the stylesheet.

 Show area names

To view the area names, enable the Show area names checkbox. In this example, there are 3 areas in the grid - top, bottom1 and bottom2.

 Extend grid lines

Enable the Extend grid lines checkbox to extend the grid lines to the edge of the viewport along each axis.

Grid overlays

The Grid overlays section contains a list of grids that are present on the page, each with a checkbox, along with various options.

 Enable overlay views of multiple grids

You can enable overlay views of multiple grids. In this example, there are 2 grid overlays enabled - main and div.snack-box, each represented with different colors.

 Customize the grid overlay color

You can customize each grid overlay color by clicking the color picker.

 Highlight the grid

Click the highlight icon to immediately highlight the HTML element, scroll to it in the page and select it in the Elements panel. Improve article


Force print preview mode

The print media query controls how your page looks when printed. To force your page into print preview mode: Press Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux, Chrome OS) to open the Command Menu. Figure 1. The Command Menu Type rendering, select Show Rendering, and then press Enter. Under Emulate CSS media select print. Figure 2. Print preview mode From here, you can view and change your CSS, like any other web page. See Get Started With Viewing And Changing CSS. Improve article


Get Started With Viewing And Changing The DOM

Complete these interactive tutorials to learn the basics of viewing and changing a page's DOM using Chrome DevTools. This tutorial assumes that you know the difference between the DOM and HTML. See Appendix: HTML versus the DOM for an explanation.

View DOM nodes

The DOM Tree of the Elements panel is where you do all DOM-related activities in DevTools.

 Inspect a node

When you're interested in a particular DOM node, Inspect is a fast way to open DevTools and investigate that node. Right-click Michelangelo below and select Inspect. Michelangelo Raphael The Elements panel of DevTools opens. <li>Michelangelo</li> is highlighted in the DOM Tree. Click the Inspect Inspect icon in the top-left corner of DevTools. Click the Tokyo text below. Tokyo Beirut Now, <li>Tokyo</li> is highlighted in the DOM Tree. Inspecting a node is also the first step towards viewing and changing a node's styles. See Get Started With Viewing And Changing CSS.

 Navigate the DOM Tree with a keyboard

Once you've selected a node in the DOM Tree, you can navigate the DOM Tree with your keyboard. Right-click Ringo below and select Inspect. <li>Ringo</li> is selected in the DOM Tree. George Ringo Paul John Press the Up arrow key 2 times. <ul> is selected. Press the Left arrow key. The <ul> list collapses. Press the Left arrow key again. The parent of the <ul> node is selected. In this case it's the <li> node containing the instructions for step 1. Press the Down arrow key 2 times so that you've re-selected the <ul> list that you just collapsed. It should look like this: <ul>...</ul> Press the Right arrow key. The list expands.

 Scroll into view

When viewing the DOM Tree, sometimes you'll find yourself interested in a DOM node that's not currently in the viewport. For example, suppose that you scrolled to the bottom of the page, and you're interested in the <h1> node at the top of the page. Scroll into view lets you quickly reposition the viewport so that you can see the node. Right-click Magritte below and select Inspect. Magritte Soutine Go to the Appendix: Scroll into view section at the bottom of this page. The instructions continue there. After completing the instructions at the bottom of the page you should jump back up to here.

 Search for nodes

You can search the DOM Tree by string, CSS selector, or XPath selector. Focus your cursor on the Elements panel. Press Control+F or Command+F (Mac). The Search bar opens at the bottom of the DOM Tree. Type The Moon is a Harsh Mistress. The last sentence is highlighted in the DOM Tree. As mentioned above, the Search bar also supports CSS and XPath selectors.

Edit the DOM

You can edit the DOM on the fly and see how those changes affect the page.

 Edit content

To edit a node's content, double-click the content in the DOM Tree. Right-click Michelle below and select Inspect. Fry Michelle In the DOM Tree, double-click Michelle. In other words, double-click the text between <li> and </li>. The text is highlighted blue to indicate that it's selected. Delete Michelle, type Leela, then press Enter to confirm the change. The text above changes from Michelle to Leela.

 Edit attributes

To edit attributes, double-click the attribute name or value. Follow the instructions below to learn how to add attributes to a node. Right-click Howard below and select Inspect. Howard Vince Double-click <li>. The text is highlighted to indicate that the node is selected. Press the Right arrow key, add a space, type style="background-color:gold", and then press Enter. The background color of the node changes to gold.

 Edit node type

To edit a node's type, double-click the type and then type in the new type. Right-click Hank below and select Inspect. Dean Hank Thaddeus Brock Double-click <li>. The text li is highlighted. Delete li, type button, then press Enter. The <li> node changes to a <button> node.

 Reorder DOM nodes

Drag nodes to reorder them. Right-click Elvis Presley below and select Inspect. Notice that it's the last item in the list. Stevie Wonder Tom Waits Chris Thile Elvis Presley In the DOM Tree, drag <li>Elvis Presley</li> to the top of the list.

 Force state

You can force nodes to remain in states like :active, :hover, :focus, :visited, and :focus-within. Hover over The Lord of the Flies below. The background color becomes orange. The Lord of the Flies Crime and Punishment Moby Dick Right-click The Lord of the Flies above and select Inspect. Right-click <li>The Lord of the Flies</li> and select Force State > :hover. See Appendix: Missing options if you don't see this option. The background color remains orange even though you're not actually hovering over the node.

 Hide a node

Press H to hide a node. Right-click The Stars My Destination below and select Inspect. The Count of Monte Cristo The Stars My Destination Press the H key. The node is hidden. Press the H key again. The node is shown again.

 Delete a node

Press Delete to delete a node. Right-click Foundation below and select Inspect. The Illustrated Man Through the Looking-Glass Foundation Press the Delete key. The node is deleted. Press Control+Z or Command+Z (Mac). The last action is undone and the node reappears.

Access nodes in the Console

DevTools provides a few shortcuts for accessing DOM nodes from the Console, or getting JavaScript references to them.

 Reference the currently-selected node with $0

When you inspect a node, the == $0 text next to the node means that you can reference this node in the Console with the variable $0. Right-click The Left Hand of Darkness below and select Inspect. The Left Hand of Darkness Dune Press the Escape key to open the Console Drawer. Type $0 and press the Enter key. The result of the expression shows that $0 evaluates to <li>The Left Hand of Darkness</li>. Hover over the result. The node is highlighted in the viewport. Click <li>Dune</li> in the DOM Tree, type $0 in the Console again, and then press Enter again. Now, $0 evaluates to <li>Dune</li>.

 Store as global variable

If you need to refer back to a node many times, store it as a global variable. Right-click The Big Sleep below and select Inspect. The Big Sleep The Long Goodbye Right-click <li>The Big Sleep</li> in the DOM Tree and select Store as global variable. See Appendix: Missing options if you don't see this option. Type temp1 in the Console and then press Enter. The result of the expression shows that the variable evaluates to the node.

 Copy JS path

Copy the JavaScript path to a node when you need to reference it in an automated test. Right-click The Brothers Karamazov below and select Inspect. The Brothers Karamazov Crime and Punishment Right-click <li>The Brothers Karamazov</li> in the DOM Tree and select Copy > Copy JS Path. A document.querySelector() expression that resolves to the node has been copied to your clipboard. Press Control+V or Command+V (Mac) to paste the expression into the Console. Press Enter to evaluate the expression.

Break on DOM changes

DevTools allows you to pause a page's JavaScript when the JavaScript modifies the DOM. See DOM change breakpoints.

Next steps

That covers most of the DOM-related features in DevTools. You can discover the rest of them by right-clicking nodes in the DOM Tree and experimenting with the other options that weren't covered in this tutorial. See also Elements panel keyboard shortcuts. Check out the Chrome DevTools homepage to discover everything else you can do with DevTools. See Community if you want to contact the DevTools team or get help from the DevTools community.

Appendix: HTML versus the DOM

This section quickly explains the difference between HTML and the DOM. When you use a web browser to request a page like https://example.com the server returns HTML like this: <!doctype html>
<html>
<head>
<title>Hello, world!</title>
</head>
<body>
<h1>Hello, world!</h1>
<p>This is a hypertext document on the World Wide Web.</p>
<script src="/script.js" async></script>
</body>
</html>
The browser parses the HTML and creates a tree of objects like this: html
head
title
body
h1
p
script
This tree of objects, or nodes, representing the page's content is called the DOM. Right now it looks the same as the HTML, but suppose that the script referenced at the bottom of the HTML runs this code: const h1 = document.querySelector('h1');
h1.parentElement.removeChild(h1);
const p = document.createElement('p');
p.textContent = 'Wildcard!';
document.body.appendChild(p);
That code removes the h1 node and adds another p node to the DOM. The complete DOM now looks like this: html
head
title
body
p
script
p
The page's HTML is now different than its DOM. In other words, HTML represents initial page content, and the DOM represents current page content. When JavaScript adds, removes, or edits nodes, the DOM becomes different than the HTML. See Introduction to the DOM to learn more.

Appendix: Scroll into view

This is a continuation of the Scroll into view section. Follow the instructions below to complete the section. The <li>Magritte</li> node should still be selected in your DOM Tree. If not, go back to Scroll into view and start over. Right-click the <li>Magritte</li> node and select Scroll into view. Your viewport scrolls back up so that you can see the Magritte node. See Appendix: Missing options if you can't see the Scroll into view option.

Appendix: Missing options

Many of the instructions in this tutorial instruct you to right-click a node in the DOM Tree and then select an option from the context menu that pops up. If you don't see the specified option in the context menu, try right-clicking away from the node text. Improve article


Console overview

This page explains how the Chrome DevTools Console makes it easier to develop web pages. The Console has 2 main uses: viewing logged messages and running JavaScript.

Viewing logged messages

Web developers often log messages to the Console to make sure that their JavaScript is working as expected. To log a message, you insert an expression like console.log('Hello, Console!') into your JavaScript. When the browser executes your JavaScript and sees an expression like that, it knows that it's supposed to log the message to the Console. For example, suppose that you're in the process of writing the HTML and JavaScript for a page: <!doctype html>
<html>
<head>
<title>Console Demo</title>
</head>
<body>
<h1>Hello, World!</h1>
<script>
console.log('Loading!');
const h1 = document.querySelector('h1');
console.log(h1.textContent);
console.assert(document.querySelector('h2'), 'h2 not found!');
const artists = [
{
first: 'René',
last: 'Magritte'
},
{
first: 'Chaim',
last: 'Soutine'
},
{
first: 'Henri',
last: 'Matisse'
}
];
console.table(artists);
setTimeout(() => {
h1.textContent = 'Hello, Console!';
console.log(h1.textContent);
}, 3000);
</script>
</body>
</html>
Figure 1 shows what the Console looks like after loading the page and waiting 3 seconds. Try to figure out which lines of code caused the browser to log the messages. Figure 1. The Console panel. Web developers log messages for 2 general reasons: Making sure that code is executing in the right order. Inspecting the values of variables at a certain moment in time. See Get Started With Logging Messages to get hands-on experience with logging. See the Console API Reference to browse the full list of console methods. The main difference between the methods is how they display the data that you're logging.

Running JavaScript

The Console is also a REPL. You can run JavaScript in the Console to interact with the page that you're inspecting. For example, Figure 2 shows the Console next to the DevTools homepage, and Figure 3 shows that same page after using the Console to change the page's title. Figure 2. The Console panel next to the DevTools homepage. Figure 3. Using the Console to change the page's title. Modifying the page from the Console is possible because the Console has full access to the page's window. DevTools has a few convenience functions that make it easier to inspect a page. For example, suppose that your JavaScript contains a function called hideModal. Running debug(hideModal) pauses your code on the first line of hideModal the next time that it's called. See Console Utilities API Reference to see the full list of utility functions. When you run JavaScript you don't have to interact with the page. You can use the Console to try out new code that's not related to the page. For example, suppose you just learned about the built-in JavaScript Array method map(), and you want to experiment with it. The Console is a good place to try out the function. See Get Started With Running JavaScript to get hands-on experience with running JavaScript in the Console. Improve article


Log messages in the Console

This interactive tutorial shows you how to log and filter messages in the Chrome DevTools Console. Figure 1. Messages in the Console. This tutorial is intended to be completed in order. It assumes that you understand the fundamentals of web development, such as how to use JavaScript to add interactivity to a page.

Set up the demo and DevTools

This tutorial is designed so that you can open up the demo and try all the workflows yourself. When you physically follow along, you're more likely to remember the workflows later. Open the demo. Optional: Move the demo to a separate window. Figure 2. This tutorial on the left, and the demo on the right. Focus the demo and then press Control+Shift+J or Command+Option+J (Mac) to open DevTools. By default DevTools opens to the right of the demo. Figure 3. DevTools opens to the right of the demo. Optional: Dock DevTools to the bottom of the window or undock it into a separate window. Figure 4. DevTools docked to the bottom of the demo. Figure 5. DevTools undocked in a separate window.

View messages logged from JavaScript

Most messages that you see in the Console come from the web developers who wrote the page's JavaScript. The goal of this section is to introduce you to the different message types that you're likely to see in the Console, and explain how you can log each message type yourself from your own JavaScript. Click the Log Info button in the demo. Hello, Console! gets logged to the Console. Figure 6. The Console after clicking Log Info. Next to the Hello, Console! message in the Console click log.js:2. The Sources panel opens and highlights the line of code that caused the message to get logged to the Console. The message was logged when the page's JavaScript called console.log('Hello, Console!'). Figure 7. DevTools opens the Sources panel after you click log.js:2. Navigate back to the Console using any of the following workflows: Click the Console tab. Press Control+[ or Command+[ (Mac) until the Console panel is in focus. Open the Command Menu, start typing Console, select the Show Console Panel command, and then press Enter. Click the Log Warning button in the demo. Abandon Hope All Ye Who Enter gets logged to the Console. Messages formatted like this are warnings. Figure 8. The Console after clicking Log Warning. Optional: Click log.js:12 to view the code that caused the message to get formatted like this, and then navigate back to Console when you're finished. Do this whenever you want to see the code that caused a message to get logged a certain way. Click the Expand stack trace leading up to the call. Figure 9. A stack trace. The stack trace is telling you that a function named logWarning was called, which in turn called a function named quoteDante. In other words, the call that happened first is at the bottom of the stack trace. You can log stack traces at any time by calling console.trace(). Click Log Error. The following error message gets logged: I'm sorry, Dave. I'm afraid I can't do that. Figure 10. An error message. Click Log Table. A table about famous artists gets logged to the Console. Note how the birthday column is only populated for one row. Check the code to figure out why that is. Figure 11. A table in the Console. Click Log Group. The names of 4 famous, crime-fighting turtles are grouped under the Adolescent Irradiated Espionage Tortoises label. Figure 12. A group of messages in the Console. Click Log Custom. A message with a red border and blue background gets logged to the Console. Figure 13. A message with custom formatting in the Console. The main idea here is that when you want to log messages to the Console from your JavaScript, you use one of the console methods. Each method formats messages differently. There are even more methods than what has been demonstrated in this section. At the end of the tutorial you'll learn how to explore the rest of the methods.

View messages logged by the browser

The browser logs messages to the Console, too. This usually happens when there's a problem with the page. Click Cause 404. The browser logs a 404 network error because the page's JavaScript tried to fetch a file that doesn't exist. Figure 14. A 404 error in the Console. Click Cause Error. The browser logs an uncaught TypeError because the JavaScript is trying to update a DOM node that doesn't exist. Figure 15. A TypeError in the Console. Click the Log Levels dropdown and enable the Verbose option if it's disabled. You'll learn more about filtering in the next section. You need to do this to make sure that the next message you log is visible. Note: If the Default Levels dropdown is disabled, you may need to close the Console Sidebar. Filter by Message Source below for more information about the Console Sidebar. Figure 16. Enabling the Verbose log level. Click Cause Violation. The page becomes unresponsive for a few seconds and then the browser logs the message [Violation] 'click' handler took 3000ms to the Console. The exact duration may vary. Figure 17. A violation in the Console.

Filter messages

On some pages you'll see the Console get flooded with messages. DevTools provides many different ways to filter out messages that aren't relevant to the task at hand.

 Filter by log level

Each console method is assigned a severity level: Verbose, Info, Warning, or Error. For example, console.log() is an Info-level message, whereas console.error() is an Error-level message. Click the Log Levels dropdown and disable Errors. A level is disabled when there is no longer a checkmark next to it. The Error-level messages disappear. Figure 18. Disabling Error-level messages in the Console. Click the Log Levels dropdown again and re-enable Errors. The Error-level messages reappear.

 Filter by text

When you want to only view messages that include an exact string, type that string into the Filter text box. Type Dave into the Filter text box. All messages that do not include the string Dave are hidden. You might also see the Adolescent Irradiated Espionage Tortoises label. That's a bug. Figure 19. Filtering out any message that does not include Dave. Delete Dave from the Filter text box. All the messages reappear.

 Filter by regular expression

When you want to show all messages that include a pattern of text, rather than a specific string, use a regular expression. Type /^[AH]/ into the Filter text box. Type this pattern into RegExr for an explanation of what it's doing. Figure 20. Filtering out any message that does not match the pattern /^[AH]/. Delete /^[AH]/ from the Filter text box. All messages are visible again.

 Filter by message source

When you want to only view the messages that came from a certain URL, use the Sidebar. Click Show Console Sidebar . Figure 21. The Sidebar. Click the Expand icon next to 12 Messages. The Sidebar shows a list of URLs that caused messages to be logged. For example, log.js caused 11 messages. Figure 22. Viewing the source of messages in the Sidebar.

 Filter by user messages

Earlier, when you clicked Log Info, a script called console.log('Hello, Console!') in order to log the message to the Console. Messages logged from JavaScript like this are called user messages. In contrast, when you clicked Cause 404, the browser logged an Error-level message stating that the requested resource could not be found. Messages like that are considered browser messages. You can use the Sidebar to filter out browser messages and only show user messages. Click 9 User Messages. The browser messages are hidden. Figure 23. Filtering out browser messages. Click 12 Messages to show all messages again.

Use the Console alongside any other panel

What if you're editing styles, but you need to quickly check the Console log for something? Use the Drawer. Click the Elements tab. Press Escape. The Console tab of the Drawer opens. It has all of the features of the Console panel that you've been using throughout this tutorial. Figure 24. The Console tab in the Drawer.

Next steps

Congratulations, you have completed the tutorial. Click Dispense Trophy to receive your trophy. See Console Reference to explore more features and workflows related to the Console UI. See Console API Reference to learn more about all of the console methods that were demonstrated in View messages logged from JavaScript and explore the other console methods that weren't covered in this tutorial. See Get Started to explore what else you can do with DevTools. Improve article


Run JavaScript in the Console

This interactive tutorial shows you how to run JavaScript in the Chrome DevTools Console. See Get Started With Logging Messages to learn how to log messages to the Console. See Debugging JavaScript to learn how to pause JavaScript code and step through it one line at a time. Figure 1. The Console.

Overview

The Console is a REPL, which stands for Read, Evaluate, Print, and Loop. It reads the JavaScript that you type into it, evaluates your code, prints out the result of your expression, and then loops back to the first step.

Set up DevTools

This tutorial is designed so that you can open up the demo and try all the workflows yourself. When you physically follow along, you're more likely to remember the workflows later. Press Command+Option+J (Mac) or Control+Shift+J (Windows, Linux, Chrome OS) to open the Console, right here on this very page. Figure 2. This tutorial on the left, and DevTools on the right.

View and change the page's JavaScript or DOM

When building or debugging a page, it's often useful to run statements in the Console in order to change how the page looks or runs. Notice the text in the button below. Type document.getElementById('hello').textContent = 'Hello, Console!' in the Console and then press Enter to evaluate the expression. Notice how the text inside the button changes. Figure 3. How the Console looks after evaluating the expression above. Below the code that you evaluated you see "Hello, Console!". Recall the 4 steps of REPL: read, evaluate, print, loop. After evaluating your code, a REPL prints the result of the expression. So "Hello, Console!" must be the result of evaluating document.getElementById('hello').textContent = 'Hello, Console!'.

Run arbitrary JavaScript that's not related to the page

Sometimes, you just want a code playground where you can test some code, or try out new JavaScript features you're not familiar with. The Console is a perfect place for these kinds of experiments. Type 5 + 15 in the Console and press Enter to evaluate the expression. The Console prints out the result of the expression below your code. Figure 4 below shows how your Console should look after evaluating this expression. Type the following code into the Console. Try typing it out, character-by-character, rather than copy-pasting it. function add(a, b=20) {
return a + b;
}
See define default values for function arguments if you're unfamiliar with the b=20 syntax. Now, call the function that you just defined. add(25); Figure 4. How the Console looks after evaluating the expressions above. add(25) evaluates to 45 because when the add function is called without a second argument, b defaults to 20.

Next steps

See Run JavaScript to explore more features related to running JavaScript in the Console. DevTools lets you pause a script in the middle of its execution. While you're paused, you can use the Console to view and change the page's window or DOM at that moment in time. This makes for a powerful debugging workflow. See Debugging JavaScript for an interactive tutorial. The Console also has a set of convenience functions that make it easier to interact with a page. For example: Rather than typing document.querySelector() to select an element, you can type $(). This syntax is inspired by jQuery, but it's not actually jQuery. It's just an alias for document.querySelector(). debug(function) effectively sets a breakpoint on the first line of that function. keys(object) returns an array containing the keys of the specified object. See Console Utilities API Reference to explore all the convenience functions. Improve article


Console features reference

This page is a reference of features related to the Chrome DevTools Console. It assumes that you're already familiar with using the Console to view logged messages and run JavaScript. If not, see Get Started. If you're looking for the API reference on functions like console.log() see Console API Reference. For the reference on functions like monitorEvents() see Console Utilities API Reference.

Open the Console

You can open the Console as a panel or as a tab in the Drawer.

 Open the Console panel

Press Control+Shift+J or Command+Option+J (Mac). Figure 1. The Console panel. To open the Console panel from the Command Menu, start typing Console and then run the Show Console command that has the Panel badge next to it. Figure 2. The command for showing the Console panel.

 Open the Console tab in the Drawer

Press Escape or click Customize And Control DevTools and then select Show Console Drawer. Figure 3. Show Console Drawer. The Drawer pops up at the bottom of your DevTools window, with the Console tab open. Figure 4. The Console tab in the Drawer. To open the Console tab from the Command Menu, start typing Console and then run the Show Console command that has the Drawer badge next to it. Figure 5. The command for showing the Console tab in the Drawer.

 Open Console Settings

Click Console Settings . Figure 6. Console Settings. The links below explain each setting: Hide Network Preserve Log Selected Context Only Group Similar Log XmlHttpRequests Eager Evaluation Autocomplete From History

 Open the Console Sidebar

Click Show Console Sidebar to show the Sidebar, which is useful for filtering. Figure 7. Console Sidebar.

View messages

This section contains features that change how messages are presented in the Console. See View messages for a hands-on walkthrough.

 Disable message grouping

Open Console Settings and disable Group similar to disable the Console's default message grouping behavior. See Log XHR and Fetch requests for an example.

 Log XHR and Fetch requests

Open Console Settings and enable Log XMLHttpRequests to log all XMLHttpRequest and Fetch requests to the Console as they happen. Figure 8. Logging XMLHttpRequest and Fetch requests. The top message in Figure 8 shows the Console's default grouping behavior. Figure 9 shows how the same log looks after disabling message grouping. Figure 9. How the logged XMLHttpRequest and Fetch requests look after ungrouping.

 Persist messages across page loads

By default the Console clears whenever you load a new page. To persist messages across page loads, Open Console Settings and then enable the Preserve Log checkbox.

 Hide network messages

By default the browser logs network messages to the Console. For example, the top message in Figure X represents a 404. Figure 10. A 404 message in the Console. To hide network messages: Open Console Settings. Enable the Hide Network checkbox.

Filter messages

There are many ways to filter out messages in the Console.

 Filter out browser messages

Open the Console Sidebar and click User Messages to only show messages that came from the page's JavaScript. Figure 11. Viewing user messages.

 Filter by log level

DevTools assigns each console.* method a severity level. There are 4 levels: Verbose, Info, Warning, and Error. For example, console.log() is in the Info group, whereas console.error() is in the Error group. The Console API Reference describes the severity level of each applicable method. Every message that the browser logs to the Console has a severity level too. You can hide any level of messages that you're not interested in. For example, if you're only interested in Error messages, you can hide the other 3 groups. Click the Log Levels dropdown to enable or disable Verbose, Info, Warning or Error messages. Figure 12. The Log Levels dropdown. You can also filter by log level by opening the Console Sidebar and then clicking Errors, Warnings, Info, or Verbose. Figure 13. Using the Sidebar to view warnings.

 Filter messages by URL

Type url: followed by a URL to only view messages that came from that URL. After you type url: DevTools shows all relevant URLs. Domains also work. For example, if https://example.com/a.js and https://example.com/b.js are logging messages, url:https://example.com enables you to focus on the messages from these 2 scripts. Figure 14. A URL filter. Type -url: to hide messages from that URL. This is called a negative URL filter. opening the Console Sidebar, expanding the User Messages section, and then clicking the URL of the script containing the messages you want to focus on. Figure 16. Viewing the messages that came from wp-ad.min.js.

 Filter out messages from different contexts

Suppose that you've got an ad on your page. The ad is embedded in an <iframe> and is generating a lot of messages in your Console. Because this ad is in a different JavaScript context, one way to hide its messages is to open Console Settings and enable the Selected Context Only checkbox.

 Filter out messages that don't match a regular expression pattern

Type a regular expression such as /[foo]\s[bar]/ in the Filter text box to filter out any messages that don't match that pattern. Spaces are not supported, use \s instead. DevTools checks if the pattern is found in the message text or the script that caused the message to be logged. Figure 17. Filtering out any messages that don't match /[gm][ta][mi]/.

Run JavaScript

This section contains features related to running JavaScript in the Console. See Run JavaScript for a hands-on walkthrough.

 Re-run expressions from history

Press the Up Arrow key to cycle through the history of JavaScript expressions that you ran earlier in the Console. Press Enter to run that expression again.

 Watch an expression's value in real-time with Live Expressions

If you find yourself typing the same JavaScript expression in the Console repeatedly, you might find it easier to create a Live Expression. With Live Expressions you type an expression once and then pin it to the top of your Console. The value of the expression updates in near real-time. See Watch JavaScript Expression Values In Real-Time With Live Expressions.

 Disable Eager Evaluation

As you type JavaScript expressions in the Console, Eager Evaluation shows a preview of that expression's return value. Open Console Settings and disable the Eager Evaluation checkbox to turn off the return value previews.

 Disable autocomplete from history

As you type out an expression, the Console's autocomplete popup shows expressions that you ran earlier. These expressions are prepended with the > character. Open Console Settings and disable the Autocomplete From History checkbox to stop showing expressions from your history. Figure 18. document.querySelector('a') and document.querySelector('img') are expressions that were evaluated earlier.

 Select JavaScript context

By default the JavaScript Context dropdown is set to top, which represents the main document's browsing context. Figure 19. The JavaScript Context dropdown. Suppose you have an ad on your page embedded in an <iframe>. You want to run JavaScript in order to tweak the ad's DOM. To do this, you first need to select the ad's browsing context from the JavaScript Context dropdown. Figure 20. Selecting a different JavaScript context.

Clear the Console

You can use any of the following workflows to clear the Console: Click Clear Console . Right-click a message and then select Clear Console. Type clear() in the Console and then press Enter. Call console.clear() from your webpage's JavaScript. Press Control+L while the Console is in focus. Improve article


Console API reference

Use the Console API to write messages to the Console from your JavaScript. See Get Started With Logging Messages To The Console for an interactive introduction to the topic. See Console Utilities API Reference if you're looking for the convenience methods like debug(function) or monitorEvents(node) which are only available from the Console.

console.assert(expression, object)

Log level: Error Writes an error to the console when expression evaluates to false. const x = 5;
const y = 3;
const reason = 'x is expected to be less than y';
console.assert(x < y, {x, y, reason});
Figure 1. The result of the console.assert() example above.

console.clear()

Clears the console. console.clear(); If Preserve Log is enabled, console.clear() is disabled. See also: Clear the Console

console.count([label])

Log level: Info Writes the number of times that count() has been invoked at the same line and with the same label. Call console.countReset([label]) to reset the count. console.count();
console.count('coffee');
console.count();
console.count();
Figure 2. The result of the console.count() example above.

console.countReset([label])

Resets a count. console.countReset();
console.countReset('coffee');

console.debug(object [, object, ...])

Log level: Verbose Identical to console.log(object [, object, ...]) except different log level. console.debug('debug'); Figure 3. The result of the console.debug() example above.

console.dir(object)

Log level: Info Prints a JSON representation of the specified object. console.dir(document.head); Figure 4. The result of the console.dir() example above.

console.dirxml(node)

Log level: Info Prints an XML representation of the descendants of node. console.dirxml(document); Figure 5. The result of the console.dirxml() example above.

console.error(object [, object, ...])

Log level: Error Prints object to the Console, formats it as an error, and includes a stack trace. console.error("I'm sorry, Dave. I'm afraid I can't do that."); Figure 6. The result of the console.error() example above.

console.group(label)

Visually groups messages together until console.groupEnd(label) is called. Use console.groupCollapsed(label) to collapse the group when it's initially logged to the Console. const label = 'Adolescent Irradiated Espionage Tortoises';
console.group(label);
console.info('Leo');
console.info('Mike');
console.info('Don');
console.info('Raph');
console.groupEnd(label);
Figure 7. The result of the console.group() example above.

console.groupCollapsed(label)

Same as console.group(label), except the group is initially collapsed when it's logged to the Console.

console.groupEnd(label)

Stops visually grouping messages. See console.group.

console.info(object [, object, ...])

Log level: Info Identical to console.log(object [, object, ...]). console.info('info'); Figure 8. The result of the console.info() example above.

console.log(object [, object, ...])

Log level: Info Prints a message to the Console. console.log('log'); Figure 9. The result of the console.log() example above.

console.table(array)

Log level: Info Logs an array of objects as a table. console.table([
{
first: 'René',
last: 'Magritte',
},
{
first: 'Chaim',
last: 'Soutine',
birthday: '18930113',
},
{
first: 'Henri',
last: 'Matisse',
}
]);
Figure 10. The result of the console.table() example above.

console.time([label])

Starts a new timer. Call console.timeEnd([label]) to stop the timer and print the elapsed time to the Console. console.time();
for (var i = 0; i < 100000; i++) {
let square = i ** 2;
}
console.timeEnd();
Figure 11. The result of the console.time() example above.

console.timeEnd([label])

Log level: Info Stops a timer. See console.time().

console.trace()

Log level: Info Prints a stack trace to the Console. const first = () => { second(); };
const second = () => { third(); };
const third = () => { fourth(); };
const fourth = () => { console.trace(); };
first();
Figure 12. The result of the console.trace() example above.

console.warn(object [, object, ...])

Log level: Warning Prints a warning to the Console. console.warn('warn'); Figure 13. The result of the console.warn() example above. Improve article


Console Utilities API reference

The Console Utilities API contains a collection of convenience functions for performing common tasks: selecting and inspecting DOM elements, displaying data in readable format, stopping and starting the profiler, and monitoring DOM events. Warning Warning: These functions only work when you call them from the Chrome DevTools Console. They won't work if you try to call them in your scripts. Looking for console.log(), console.error(), and the rest of the console.* functions? See Console API Reference.

$_

$_ returns the value of the most recently evaluated expression. In the following example, a simple expression (2 + 2) is evaluated. The $_ property is then evaluated, which contains the same value: In the next example, the evaluated expression initially contains an array of names. Evaluating $_.length to find the length of the array, the value stored in $_ changes to become the latest evaluated expression, 4:

$0 - $4

The $0, $1, $2, $3 and $4 commands work as a historical reference to the last five DOM elements inspected within the Elements panel or the last five JavaScript heap objects selected in the Profiles panel. $0 returns the most recently selected element or JavaScript object, $1 returns the second most recently selected one, and so on. In the following example, an img element is selected in the Elements panel. In the Console drawer, $0 has been evaluated and displays the same element: The image below shows a different element selected in the same page. The $0 now refers to newly selected element, while $1 returns the previously selected one:

$(selector, [startNode])

$(selector) returns the reference to the first DOM element with the specified CSS selector. When called with one argument, this function is an alias for the document.querySelector() function. The following example returns a reference to the first <img> element in the document: Right-click on the returned result and select 'Reveal in Elements Panel' to find it in the DOM, or 'Scroll in to View' to show it on the page. The following example returns a reference to the currently selected element and displays its src property: This function also supports a second parameter, startNode, that specifies an 'element' or Node from which to search for elements. The default value of this parameter is document. The following example returns a reference to the first element after the currently selected Node and displays its src properly: Note: If you are using a library such as jQuery that uses $, this functionality will be overwritten, and $ will correspond to that library's implementation.

$$(selector, [startNode])

$$(selector) returns an array of elements that match the given CSS selector. This command is equivalent to calling document.querySelectorAll(). The following example uses $$() to create an array of all <img> elements in the current document and displays the value of each element's src property: let images = $$('img');
for (let each of images) {
console.log(each.src);
}
This function also supports a second parameter, startNode, that specifies an element or Node from which to search for elements. The default value of this parameter is document. This modified version of the previous example uses $$() to create an array of all <img> elements that appear in the current document after the selected Node: let images = $$('img', document.querySelector('.devsite-header-background'));
for (let each of images) {
console.log(each.src);
}
Note: Press Shift + Enter in the console to start a new line without executing the script.

$x(path, [startNode])

$x(path) returns an array of DOM elements that match the given XPath expression. For example, the following returns all the <p> elements on the page: $x("//p") The following example returns all the <p> elements that contain <a> elements: $x("//p[a]") Similar to the other selector functions, $x(path) has an optional second parameter, startNode, that specifies an element or Node from which to search for elements.

clear()

clear() clears the console of its history. clear();

copy(object)

copy(object) copies a string representation of the specified object to the clipboard. copy($0);

debug(function)

When the specified function is called, the debugger is invoked and breaks inside the function on the Sources panel allowing to step through the code and debug it. debug(getData); Use undebug(fn) to stop breaking on the function, or use the UI to disable all breakpoints. For more information on breakpoints, see Pause Your Code With Breakpoints.

dir(object)

dir(object) displays an object-style listing of all the specified object's properties. This method is an alias for the Console API's console.dir() method. The following example shows the difference between evaluating document.body directly in the command line, and using dir() to display the same element: document.body;
dir(document.body);
console.dir() entry in the Console API.

dirxml(object)

dirxml(object) prints an XML representation of the specified object, as seen in the Elements tab. This method is equivalent to the console.dirxml() method.

inspect(object/function)

inspect(object/function) opens and selects the specified element or object in the appropriate panel: either the Elements panel for DOM elements or the Profiles panel for JavaScript heap objects. The following example opens the document.body in the Elements panel: inspect(document.body); When passing a function to inspect, the function opens the document up in the Sources panel for you to inspect.

getEventListeners(object)

getEventListeners(object) returns the event listeners registered on the specified object. The return value is an object that contains an array for each registered event type (click or keydown, for example). The members of each array are objects that describe the listener registered for each type. For example, the following lists all the event listeners registered on the document object: getEventListeners(document); If more than one listener is registered on the specified object, then the array contains a member for each listener. In the following example, there are two event listeners registered on the document element for the click event: You can further expand each of these objects to explore their properties:

keys(object)

keys(object) returns an array containing the names of the properties belonging to the specified object. To get the associated values of the same properties, use values(). For example, suppose your application defined the following object: let player1 = { "name": "Ted", "level": 42 }; Assuming player1 was defined in the global namespace (for simplicity), typing keys(player1) and values(player1) in the console results in the following:

monitor(function)

When the function specified is called, a message is logged to the console that indicates the function name along with the arguments that are passed to the function when it was called. function sum(x, y) {
return x + y;
}
monitor(sum);
Use unmonitor(function) to cease monitoring.

monitorEvents(object[, events])

When one of the specified events occurs on the specified object, the Event object is logged to the console. You can specify a single event to monitor, an array of events, or one of the generic events "types" mapped to a predefined collection of events. See examples below. The following monitors all resize events on the window object. monitorEvents(window, "resize"); The following defines an array to monitor both "resize" and "scroll" events on the window object: monitorEvents(window, ["resize", "scroll"]) You can also specify one of the available event "types", strings that map to predefined sets of events. The table below lists the available event types and their associated event mappings:
Event type & Corresponding mapped events
mouse"mousedown", "mouseup", "click", "dblclick", "mousemove", "mouseover", "mouseout", "mousewheel"
key"keydown", "keyup", "keypress", "textInput"
touch "touchstart", "touchmove", "touchend", "touchcancel"
control"resize", "scroll", "zoom", "focus", "blur", "select", "change", "submit", "reset"
For example, the following uses the "key" event type all corresponding key events on an input text field currently selected in the Elements panel. monitorEvents($0, "key"); Below is sample output after typing a characters in the text field:

profile([name]) and profileEnd([name])

profile() starts a JavaScript CPU profiling session with an optional name. profileEnd() completes the profile and displays the results in the Profile panel. (See also Speed Up JavaScript Execution.) To start profiling: profile("My profile") To stop profiling and display the results in the Profiles panel: profileEnd("My profile") Profiles can also be nested. For example, this will work in any order: profile('A');
profile('B');
profileEnd('A');
profileEnd('B');
Result in the profiles panel: Note: Multiple CPU profiles can operate at once and you aren't required to close them out in creation order.

queryObjects(Constructor)

Call queryObjects(Constructor) from the console to return an array of objects that were created with the specified constructor. For example: queryObjects(Promise). Returns all instances of Promise. queryObjects(HTMLElement). Returns all HTML elements. queryObjects(foo), where foo is a class name. Returns all objects that were instantiated via new foo(). The scope of queryObjects() is the currently-selected execution context in the console.

table(data[, columns])

Log object data with table formatting by passing in a data object in with optional column headings. For example, to display a list of names using a table in the console, you would do: let names = [
{ firstName: "John", lastName: "Smith" },
{ firstName: "Jane", lastName: "Doe" },
];
table(names);

undebug(function)

undebug(function) stops the debugging of the specified function so that when the function is called, the debugger is no longer invoked. This is used in concert with debug(fn). undebug(getData);

unmonitor(function)

unmonitor(function) stops the monitoring of the specified function. This is used in concert with monitor(fn). unmonitor(getData);

unmonitorEvents(object[, events])

unmonitorEvents(object[, events]) stops monitoring events for the specified object and events. For example, the following stops all event monitoring on the window object: unmonitorEvents(window); You can also selectively stop monitoring specific events on an object. For example, the following code starts monitoring all mouse events on the currently selected element, and then stops monitoring "mousemove" events (perhaps to reduce noise in the console output): monitorEvents($0, "mouse");
unmonitorEvents($0, "mousemove");

values(object)

values(object) returns an array containing the values of all properties belonging to the specified object. values(object); Improve article


Watch JavaScript values in real-time with Live Expressions

If you find yourself typing the same JavaScript expression in the Console repeatedly, you might find it easier to create a Live Expression. With Live Expressions you type an expression once and then pin it to the top of your Console. The value of the expression updates in near real-time.

Create a Live Expression

Open the Console. Click Create Live Expression . The Live Expression text box appears. Figure 1 Typing document.activeElement into the Live Expression text box. Type Control+Enter or Command+Enter (Mac) to save the expression, or click outside of the Live Expression text box. Improve article


Find Unused JavaScript And CSS With The Coverage Tab

The Coverage tab in Chrome DevTools can help you find unused JavaScript and CSS code. Removing unused code can speed up your page load and save your mobile users cellular data. Figure 1. Analyzing code coverage. Caution A word of warning. Finding unused code is relatively easy. But refactoring a codebase so that each page only ships the JavaScript and CSS that it needs can be difficult. This guide doesn't cover how to refactor a codebase to avoid unused code because these refactors depend highly on your technology stack.

Overview

Shipping unused JavaScript or CSS is a common problem in web development. For example, suppose that you want to use Bootstrap's button component on your page. To use the button component you need to add a link to Bootstrap's stylesheet in your HTML, like this: ...
<head>
...
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
crossorigin="anonymous">

...
</head>
...
This stylesheet doesn't just include the code for the button component. It contains the CSS for all of Bootstrap's components. But you're not using any of the other Bootstrap components. So your page is downloading a bunch of CSS that it doesn't need. This extra CSS is a problem for the following reasons: The extra code slows down your page load. See Render-Blocking CSS. If a user accesses the page on a mobile device, the extra code uses up their cellular data.

Open the Coverage tab

Open the Command Menu. Start typing coverage, select the Show Coverage command, and then press Enter to run the command. The Coverage tab opens in the Drawer. Figure 2. The Coverage tab.

Record code coverage

Click one of the following buttons in the Coverage tab: Click Start Instrumenting Coverage And Reload Page if you want to see what code is needed to load the page. Click Instrument Coverage if you want to see what code is used after interacting with the page. Click Stop Instrumenting Coverage And Show Results when you want to stop recording code coverage.

Analyze code coverage

The table in the Coverage tab shows you what resources were analyzed, and how much code is used within each resource. Click a row to open that resource in the Sources panel and see a line-by-line breakdown of used code and unused code. Figure 3. A code coverage report. The URL column is the URL of the resource that was analyzed. The Type column says whether the resource contains CSS, JavaScript, or both. The Total Bytes column is the total size of the resource in bytes. The Unused Bytes column is the number of bytes that weren't used. The last, unnamed column is a visualization of the Total Bytes and Unused Bytes columns. The red section of the bar is unused bytes. The green section is used bytes. Improve article


Inspect network activity

This is a hands-on tutorial of some of the most commonly-used DevTools features related to inspecting a page's network activity. See Network Reference if you'd like to browse features instead. Read on, or watch the video version of this tutorial:

When to use the Network panel

In general, use the Network panel when you need to make sure that resources are being downloaded or uploaded as expected. The most common use cases for the Network panel are: Making sure that resources are actually being uploaded or downloaded at all. Inspecting the properties of an individual resource, such as its HTTP headers, content, size, and so on. If you're looking for ways to improve page load performance, don't start with the Network panel. There are many types of load performance issues that aren't related to network activity. Start with the Audits panel because it gives you targeted suggestions on how to improve your page. See Optimize Website Speed.

Open the Network panel

To get the most out of this tutorial, open up the demo and try out the features on the demo page. Open the Get Started Demo. Figure 1. The demo You might prefer to move the demo to a separate window. Figure 2. The demo in one window and this tutorial in a different window Open DevTools by pressing Control+Shift+J or Command+Option+J (Mac). The Console panel opens. Figure 3. The Console You might prefer to dock DevTools to the bottom of your window. Figure 4. DevTools docked to the bottom of the window Click the Network tab. The Network panel opens. Figure 5. DevTools docked to the bottom of the window Right now the Network panel is empty. That's because DevTools only logs network activity while it's open and no network activity has occurred since you opened DevTools.

Log network activity

To view the network activity that a page causes: Reload the page. The Network panel logs all network activity in the Network Log. Figure 6. The Network Log Each row of the Network Log represents a resource. By default the resources are listed chronologically. The top resource is usually the main HTML document. The bottom resource is whatever was requested last. Each column represents information about a resource. Figure 6 shows the default columns: Status. The HTTP response code. Type. The resource type. Initiator. What caused a resource to be requested. Clicking a link in the Initiator column takes you to the source code that caused the request. Time. How long the request took. Waterfall. A graphical representation of the different stages of the request. Hover over a Waterfall to see a breakdown. Note The graph above the Network Log is called the Overview. You won't be using it in this tutorial, so you can hide it if you prefer. See Hide the Overview pane. So long as you've got DevTools open, it will record network activity in the Network Log. To demonstrate this, first look at the bottom of the Network Log and make a mental note of the last activity. Now, click the Get Data button in the demo. Look at the bottom of the Network Log again. There's a new resource called getstarted.json. Clicking the Get Data button caused the page to request this file. Figure 7. A new resource in the Network Log

Show more information

The columns of the Network Log are configurable. You can hide columns that you're not using. There are also many columns that are hidden by default which you may find useful. Right-click the header of the Network Log table and select Domain. The domain of each resource is now shown. Figure 8. Enabling the Domain column Tip You can see the full URL of a resource by hovering over its cell in the Name column.

Simulate a slower network connection

The network connection of the computer that you use to build sites is probably faster than the network connections of the mobile devices of your users. By throttling the page you can get a better idea of how long a page takes to load on a mobile device. Click the Throttling dropdown, which is set to Online by default. Figure 9. Enabling throttling Select Slow 3G. Figure 10. Selecting Slow 3G Long-press Reload and then select Empty Cache And Hard Reload. Figure 11. Empty Cache And Hard Reload On repeat visits, the browser usually serves some files from its cache, which speeds up the page load. Empty Cache And Hard Reload forces the browser to go the network for all resources. This is helpful when you want to see how a first-time visitor experiences a page load. Note The Empty Cache And Hard Reload workflow is only available when DevTools is open.

Capture screenshots

Screenshots let you see how a page looked over time while it was loading. Click Capture Screenshots . Reload the page again via the Empty Cache And Hard Reload workflow. See Simulate a slower connection if you need a reminder on how to do this. The Screenshots pane provides thumbnails of how the page looked at various points during the loading process. Figure 12. Screenshots of the page load Click the first thumbnail. DevTools shows you what network activity was occurring at that moment in time. Figure 13. The network activity that was happening during the first screenshot Click Capture Screenshots again to close the Screenshots pane. Reload the page again.

Inspect a resource's details

Click a resource to learn more information about it. Try it now: Click getstarted.html. The Headers tab is shown. Use this tab to inspect HTTP headers. Figure 14. The Headers tab Click the Preview tab. A basic rendering of the HTML is shown. Figure 15. The Preview tab This tab is helpful when an API returns an error code in HTML and it's easier to read the rendered HTML than the HTML source code, or when inspecting images. Click the Response tab. The HTML source code is shown. Figure 16. The Response tab Tip When a file is minified, clicking the Format button at the bottom of the Response tab re-formats the file's contents for readability. Click the Timing tab. A breakdown of the network activity for this resource is shown. Figure 17. The Timing tab Click Close to view the Network Log again. Figure 18. The Close button

Search network headers and responses

Use the Search pane when you need to search the HTTP headers and responses of all resources for a certain string or regular expression. For example, suppose you want to check if your resources are using reasonable cache policies. Click Search . The Search pane opens to the left of the Network log. Figure 19. The Search pane Type Cache-Control and press Enter. The Search pane lists all instances of Cache-Control that it finds in resource headers or content. Figure 20. Search results for Cache-Control Click a result to view it. If the query was found in a header, the Headers tab opens. If the query was found in content, the Response tab opens. Figure 21. A search result highlighted in the Headers tab Close the Search pane and the Timing tab. Figure 22. The Close buttons

Filter resources

DevTools provides numerous workflows for filtering out resources that aren't relevant to the task at hand. Figure 23. The Filters toolbar The Filters toolbar should be enabled by default. If not: Click Filter to show it.

 Filter by string, regular expression, or property

The Filter text box supports many different types of filtering. Type png into the Filter text box. Only the files that contain the text png are shown. In this case the only files that match the filter are the PNG images. Figure 24. A string filter Type /.*\.[cj]s+$/. DevTools filters out any resource with a filename that doesn't end with a j or a c followed by 1 or more s characters. Figure 25. A regular expression filter Type -main.css. DevTools filters out main.css. If any other file matched the pattern they would also be filtered out. Figure 26. A negative filter Type domain:raw.githubusercontent.com into the Filter text box. DevTools filters out any resource with a URL that does not match this domain. Figure 27. A property filter See Filter requests by properties for the full list of filterable properties. Clear the Filter text box of any text.

 Filter by resource type

To focus in on a certain type of file, such as stylesheets: Click CSS. All other file types are filtered out. Figure 28. Showing CSS files only To also see scripts, hold Control or Command (Mac) and then click JS. Figure 29. Showing CSS and JS files only Click All to remove the filters and see all resources again. See Filter requests for other filtering workflows.

Block requests

How does a page look and behave when some of its resources aren't available? Does it fail completely, or is it still somewhat functional? Block requests to find out: Press Control+Shift+P or Command+Shift+P (Mac) to open the Command Menu. Figure 30. The Command Menu Type block, select Show Request Blocking, and press Enter. Figure 31. Show Request Blocking Click Add Pattern . Type main.css. Figure 32. Blocking main.css Click Add. Reload the page. As expected, the page's styling is slightly messed up because its main stylesheet has been blocked. Note the main.css row in the Network Log. The red text means that the resource was blocked. Figure 33. main.css has been blocked Uncheck the Enable request blocking checkbox.

Next steps

Congratulations, you have completed the tutorial. Click Dispense Award to receive your award. Check out the Network Reference to discover more DevTools features related to inspecting network activity. Improve article


Network features reference

Discover new ways to analyze how your page loads in this comprehensive reference of Chrome DevTools network analysis features. Note: This reference is based on Chrome 58. If you use another version of Chrome, the UI and features of DevTools may be different. Check chrome://help to see what version of Chrome you're running.

Record network requests

By default, DevTools records all network requests in the Network panel, so long as DevTools is open. Figure 1. The Network panel

 Stop recording network requests

To stop recording requests: Click Stop recording network log on the Network panel. It turns grey to indicate that DevTools is no longer recording requests. Press Command+E (Mac) or Control+E (Windows, Linux) while the Network panel is in focus.

 Clear requests

Click Clear on the Network panel to clear all requests from the Requests table. Figure 2. Clear, outlined in blue

 Save requests across page loads

To save requests across page loads, check the Preserve log checkbox on the Network panel. DevTools saves all requests until you disable Preserve log. Figure 3. The Preserve Log checkbox, outlined in blue

 Capture screenshots during page load

Capture screenshots to analyze what users see as they wait for your page to load. To enable screenshots, open Settings inside the Network panel and check Capture screenshots. Reload the page while the Network panel is in focus to capture screenshots. Once captured, you can interact with screenshots in the following ways: Hover over a screenshot to view the point at which that screenshot was captured. A yellow line appears on the Overview pane. Click a screenshot's thumbnail to filter out any requests that occurred after the screenshot was captured. Double-click a thumbnail to zoom in on it. Figure 4. Capture screenshots enabled, showing loading screenshots over time.

 Replay XHR request

To replay an XHR request, right-click the request in the Requests table and select Replay XHR. Figure 5. Selecting Replay XHR

Change loading behavior

 Emulate a first-time visitor by disabling the browser cache

To emulate how a first-time user experiences your site, check the Disable cache checkbox. DevTools disables the browser cache. This more accurately emulates a first-time user's experience, because requests are served from the browser cache on repeat visits. Figure 6. The Disable Cache checkbox, outlined in blue

Disable the browser cache from the Network Conditions drawer

If you want to disable the cache while working in other DevTools panels, use the Network Conditions drawer. Open the Network Conditions drawer. Check or uncheck the Disable cache checkbox.

 Manually clear the browser cache

To manually clear the browser cache at any time, right-click anywhere in the Requests table and select Clear Browser Cache. Figure 7. Selecting Clear Browser Cache

 Emulate offline

There's a new class of web apps, called Progressive Web Apps, which can function offline with the help of service workers. When you're building this type of app, it's useful to be able to quickly simulate a device that has no data connection. Check the Offline checkbox to simulate a completely offline network experience. Figure 8. The Offline checkbox, outlined in blue

 Emulate slow network connections

Emulate 2G, 3G, and other connection speeds from the Network Throttling menu. Figure 9. The Network Throttling menu, outlined in blue You can select from a variety of presets, such as Regular or Good 2G. You can also add your own custom presets by opening the Network Throttling menu and selecting Custom > Add. DevTools displays a warning icon next to the Network tab to remind you that throttling is enabled.

Emulate slow network connections from the Network Conditions drawer

If you want to throttle the network connection while working in other DevTools panels, use the Network Conditions drawer. Open the Network Conditions drawer. Select your desired connection speed from the Network Throttling menu.

 Manually clear browser cookies

To manually clear browser cookies at any time, right-click anywhere in the Requests table and select Clear Browser Cookies. Figure 10. Selecting Clear Browser Cookies

 Override the user agent

To manually override the user agent: Open the Network Conditions drawer. Uncheck Select automatically. Choose a user agent option from the menu, or enter a custom one in the text box.

Filter requests

 Filter requests by properties

Use the Filter text box to filter requests by properties, such as the domain or size of the request. If you can't see the text box, the Filters pane is probably hidden. See Hide the Filters pane. Figure 11. The Filters text box, outlined in blue You can use multiple properties simultaneously by separating each property with a space. For example, mime-type:image/gif larger-than:1K displays all GIFs that are larger than one kilobyte. These multi-property filters are equivalent to AND operations. OR operations are currently not supported. Below is a complete list of supported properties. cookie-domain. Show the resources that set a specific cookie domain. cookie-name. Show the resources that set a specific cookie name. cookie-path. Show the resources that set a specific cookie path. cookie-value. Show the resources that set a specific cookie value. domain. Only display resources from the specified domain. You can use a wildcard character (*) to include multiple domains. For example, *.com displays resources from all domain names ending in .com. DevTools shows a populates the autocomplete dropdown menu with all of the domains it has encountered. has-response-header. Show the resources that contain the specified HTTP response header. DevTools populates the autocomplete dropdown with all of the response headers that it has encountered. is. Use is:running to find WebSocket resources. larger-than. Show resources that are larger than the specified size, in bytes. Setting a value of 1000 is equivalent to setting a value of 1k. method. Show resources that were retrieved over a specified HTTP method type. DevTools populates the autocomplete dropdown with all of the HTTP methods it has encountered. mime-type. Show resources of a specified MIME type. DevTools populates the autocomplete dropdown with all MIME types it has encountered. mixed-content. Show all mixed content resources (mixed-content:all) or just the ones that are currently displayed (mixed-content:displayed). priority. Show resources whose priority level matches the specified value. resource-type. Show resources of a resource type, e.g. image. DevTools populates the autocomplete dropdown with all resource types it has encountered. scheme. Show resources retrieved over unprotected HTTP (scheme:http) or protected HTTPS (scheme:https). set-cookie-domain. Show the resources that have a Set-Cookie header with a Domain attribute that matches the specified value. DevTools populates the autocomplete with all of the cookie domains that it has encountered. set-cookie-name. Show the resources that have a Set-Cookie header with a name that matches the specified value. DevTools populates the autocomplete with all of the cookie names that it has encountered. set-cookie-value. Show the resources that have a Set-Cookie header with a value that matches the specified value. DevTools populates the autocomplete with all of the cookie values that it has encountered. status-code. Only show resources whose HTTP status code match the specified code. DevTools populates the autocomplete dropdown menu with all of the status codes it has encountered. url. Show the resources that have a url matching the specified value.

 Filter requests by type

To filter requests by request type, click the XHR, JS, CSS, Img, Media, Font, Doc, WS (WebSocket), Manifest, or Other (any other type not listed here) buttons on the Network panel. If you can't see these buttons, the Filters pane is probably hidden. See Hide the Filters pane. To enable multiple type filters simultaneously, hold Command (Mac) or Control (Windows, Linux) and then click. Figure 12. Using the Type filters to display JS, CSS, and Doc[ument] resources.

 Filter requests by time

Click and drag left or right on the Overview pane to only display requests that were active during that time frame. The filter is inclusive. Any request that was active during the highlighted time is shown. Figure 13. Filtering out any requests that weren't active around 2500ms

 Hide data URLs

Data URLs are small files embedded into other documents. Any request that you see in the Requests table that starts with data: is a data URL. Check the Hide data URLs checkbox to hide these requests. Figure 14. The Hide Data URLs checkbox

Sort requests

By default, the requests in the Requests table are sorted by initiation time, but you can sort the table using other criteria.

 Sort by column

Click the header of any column in the Requests to sort requests by that column.

 Sort by activity phase

To change how the Waterfall sorts requests, right-click the header of the Requests table, hover over Waterfall, and select one of the following options: Start Time. The first request that was initiated is at the top. Response Time. The first request that started downloading is at the top. End Time. The first request that finished is at the top. Total Duration. The request with the shortest connection setup and request / response is at the top. Latency. The request that waited the shortest time for a response is at the top. These descriptions assume that each respective option is ranked from shortest to longest. Clicking on the Waterfall column's header reverses the order. Figure 15. Sorting the Waterfall by total duration. The lighter portion of each bar is time spent waiting. The darker portion is time spent downloading bytes.

Analyze requests

So long as DevTools is open, it logs all requests in the Network panel. Use the Network panel to analyze requests.

 View a log of requests

Use the Requests table to view a log of all requests made while DevTools has been open. Clicking or hovering over requests reveals more information about them. Figure 16. The Requests table, outlined in blue The Requests table displays the following columns by default: Name. The filename of, or an identifier for, the resource. Status. The HTTP status code. Type. The MIME type of the requested resource. Initiator. The following objects or processes can initiate requests: Parser. Chrome's HTML parser. Redirect. An HTTP redirect. Script. A JavaScript function. Other. Some other process or action, such as navigating to a page via a link or entering a URL in the address bar. Size. The combined size of the response headers plus the response body, as delivered by the server. Time. The total duration, from the start of the request to the receipt of the final byte in the response. Waterfall. A visual breakdown of each request's activity.

Add or remove columns

Right-click the header of the Requests table and select an option to hide or show it. Currently displayed options have checkmarks next to them. Figure 17. Adding a column to the Requests table.

Add custom columns

To add a custom column to the Requests table, right-click the header of the Requests table and select Response Headers > Manage Header Columns. Figure 18. Adding a custom column to the Requests table.

 View the timing of requests in relation to one another

Use the Waterfall to view the timing of requests in relation to one another. By default, the Waterfall is organized by the start time of the requests. So, requests that are farther to the left started earlier than those that are farther to the right. See Sort by activity phase to see the different ways that you can sort the Waterfall. Figure 19. The Waterfall column of the Requests pane.

 Analyze the frames of a WebSocket Connection

To view the frames of a WebSocket connection: Click the URL of the WebSocket connection, under the Name column of the Requests table. Click the Frames tab. The table shows the last 100 frames. To refresh the table, re-click the name of the WebSocket connection under the Name column of the Requests table. Figure 20. The Frames tab, outlined in blue The table contains three columns: Data. The message payload. If the message is plain text, it's displayed here. For binary opcodes, this column displays the opcode's name and code. The following opcodes are supported: Continuation Frame, Binary Frame, Connection Close Frame, Ping Frame, and Pong Frame. Length. The length of the message payload, in bytes. Time. The time when the message was received or sent. Messages are color-coded according to their type: Outgoing text messages are light-green. Incoming text messages are white. WebSocket opcodes are light-yellow. Errors are light-red.

 View a preview of a response body

To view a preview of a response body: Click the URL of the request, under the Name column of the Requests table. Click the Preview tab. This tab is mostly useful for viewing images. Figure 21. The Preview tab, outlined in blue

 View a response body

To view the response body to a request: Click the URL of the request, under the Name column of the Requests table. Click the Response tab. Figure 22. The Response tab, outlined in blue

 View HTTP headers

To view HTTP header data about a request: Click on the URL of the request, under the Name column of the Requests table. Click the Headers tab. Figure 23. The Headers tab, outlined in blue

View HTTP header source

By default, the Headers tab shows header names alphabetically. To view the HTTP header names in the order they were received: Open the Headers tab for the request you're interested in. See View HTTP headers. Click view source, next to the Request Header or Response Header section.

Provisional headers are shown

There are times where the headers will show a warning message "Provisional headers are shown...". It could be due to the request not sent over the network (served from a local cache), which doesn't store the original request headers. In this case, you can disable caching to see the full request headers. It could also be due to the network resource not valid (e.g. Try fetch("https://jec.fyi.com/unknown-url/") in the Console). DevTools could also display only provisional header due to security reasons.

 View query string parameters

To view the query string parameters of a URL in a human-readable format: Open the Headers tab for the request you're interested in. See View HTTP headers. Go to the Query String Parameters section. Figure 24. The Query String Parameters section, outlined in blue

View query string parameters source

To view the query string parameter source of a request: Go to the Query String Parameters section. See View query string parameters. Click view source.

View URL-encoded query string parameters

To view query string parameters in a human-readable format, but with encodings preserved: Go to the Query String Parameters section. See View query string parameters. Click view URL encoded.

 View cookies

To view the cookies sent in a request's HTTP header: Click the URL of the request, under the Name column of the Requests table. Click the Cookies tab. See Fields for a description of each of the columns. Figure 25. The Cookies tab, outlined in blue

 View the timing breakdown of a request

To view the timing breakdown of a request: Click the URL of the request, under the Name column of the Requests table. Click the Timing tab. See Preview a timing breakdown for a faster way to access this data. See Timing breakdown phases explained for more information about each of the phases that you may see in the Timing tab. Figure 26. The Timing tab, outlined in blue Here's more information about each of the phases. See View timing breakdown for another way to access this view.

Preview a timing breakdown

To view a preview of the timing breakdown of a request, hover over the request's entry in the Waterfall column of the Requests table. See View the timing breakdown of a request for a way to access this data that does not require hovering. Figure 27. Previewing the timing breakdown of a request

Timing breakdown phases explained

Here's more information about each of the phases you may see in the Timing tab: Queueing. The browser queues requests when: There are higher priority requests. There are already six TCP connections open for this origin, which is the limit. Applies to HTTP/1.0 and HTTP/1.1 only. The browser is briefly allocating space in the disk cache Stalled. The request could be stalled for any of the reasons described in Queueing. DNS Lookup. The browser is resolving the request's IP address. Initial connection. The browser is establishing a connection, including TCP handshakes/retries and negotiating an SSL. Proxy negotiation. The browser is negotiating the request with a proxy server. Request sent. The request is being sent. ServiceWorker Preparation. The browser is starting up the service worker. Request to ServiceWorker. The request is being sent to the service worker. Waiting (TTFB). The browser is waiting for the first byte of a response. TTFB stands for Time To First Byte. This timing includes 1 round trip of latency and the time the server took to prepare the response. Content Download. The browser is receiving the response. Receiving Push. The browser is receiving data for this response via HTTP/2 Server Push. Reading Push. The browser is reading the local data previously received.

 View initiators and dependencies

To view the initiators and dependencies of a request, hold Shift and hover over the request in the Requests table. DevTools colors initiators green, and dependencies red. Figure 28. Viewing the initiators and dependencies of a request When the Requests table is ordered chronologically, the first green request above the request that you're hovering over is the initiator of the dependency. If there's another green request above that, that higher request is the initiator of the initiator. And so on.

 View load events

DevTools displays the timing of the DOMContentLoaded and load events in multiple places on the Network panel. The DOMContentLoaded event is colored blue, and the load event is red. Figure 29. The locations of the DOMContentLoaded and load events in the Network panel

 View the total number of requests

The total number of requests is listed in the Summary pane, at the bottom of the Network panel. Caution Caution: This number only tracks requests that have been logged since DevTools was opened. If other requests occurred before DevTools was opened, those requests aren't counted. Figure 30. The total number of requests since DevTools was opened

 View the total download size

The total download size of requests is listed in the Summary pane, at the bottom of the Network panel. Caution Caution: This number only tracks requests that have been logged since DevTools was opened. If other requests occurred before DevTools was opened, those requests aren't counted. Figure 31. The total download size of requests See View the uncompressed size of a resource to see how large resources are after the browser uncompresses them.

 View the stack trace that caused a request

When a JavaScript statement causes a resource to be requested, hover over the Initiator column to view the stack trace leading up to the request. Figure 32. The stack trace leading up to a resource request

 View the uncompressed size of a resource

Click Use Large Request Rows and then look at the bottom value of the Size column. Figure 33. The compressed size of the jquery-bundle.js file that was sent over the network was 30.9 KB, whereas the uncompressed size was 86.3 KB

Export requests data

 Save all network requests to a HAR file

To save all network requests to a HAR file: Right-click any request in the Requests table. Select Save as HAR with Content. DevTools saves all requests that have occurred since you opened DevTools to the HAR file. There is no way to filter requests, or to save just a single request. Once you've got a HAR file, you can import it back into DevTools for analysis. Just drag-and-drop the HAR file into the Requests table. See also HAR Analyzer. Figure 34. Selecting Save as HAR with Content

 Copy one or more requests to the clipboard

Under the Name column of the Requests table, right-click a request, hover over Copy, and select one of the following options: Copy Link Address. Copy the request's URL to the clipboard. Copy Response. Copy the response body to the clipboard. Copy as cURL. Copy the request as a cURL command. Copy All as cURL. Copy all requests as a chain of cURL commands. Copy All as HAR. Copy all requests as HAR data. Figure 35. Selecting Copy Response

Change the layout of the Network panel

Expand or collapse sections of the Network panel UI to focus on what's important to you.

 Hide the Filters pane

By default, DevTools shows the Filters pane. Click Filter to hide it. Figure 36. Hide Filters, outlined in blue

 Use large request rows

Use large rows when you want more whitespace in your network requests table. Some columns also provide a little more information when using large rows. For example, the bottom value of the Size column is the uncompressed size of a request. Open Settings and click Use large request rows to enable large rows. Figure 37. Large Request Rows, outlined in blue

 Hide the Overview pane

By default, DevTools shows the Overview pane. Open Settings and uncheck the Show overview checkbox to hide it. Figure 38. Hide Overview, outlined in blue Improve article


View, edit, and delete cookies

HTTP Cookies are mainly used to manage user sessions, store user personalization preferences, and track user behavior. They are also the cause of all of those annoying "this page uses cookies" consent forms that you see across the web. This guide teaches you how to view, edit, and delete a page's cookies with Chrome DevTools.

Open the Cookies pane

Open Chrome DevTools. Click the Application tab to open the Application panel. Under Storage expand Cookies, then select an origin. Figure 1. The Cookies pane

Fields

The Cookies table contains the following fields: Name. The cookie's name. Value. The cookie's value. Domain. The hosts that are allowed to receive the cookie. Path. The URL that must exist in the requested URL in order to send the Cookie header. Expires / Max-Age. The cookie's expiration date or maximum age. For session cookies this value is always Session. Size. The cookie's size, in bytes. HTTP. If true, this field indicates that the cookie should only be used over HTTP, and JavaScript modification is not allowed. Secure. If true, this field indicates that the cookie can only be sent to the server over a secure, HTTPS connection. SameSite. Contains strict or lax if the cookie is using the experimental SameSite attribute. SameParty. If true, this field indicates that the cookie is allowed to be set or sent in contexts where all ancestor frames belong to the same First-Party Set. Priority. Contains low, medium (default), or high if using deprecated cookie Priority attribute.

Filter cookies

Use the Filter text box to filter cookies by Name or Value. Filtering by other fields is not supported. Figure 2. Filtering out any cookies that don't contain the text NID

Edit a cookie

The Name, Value, Domain, Path, and Expires / Max-Age fields are editable. Double-click a field to edit it. Figure 3. Setting the name of a cookie to DEVTOOLS!

Delete cookies

Select a cookie and then click Delete Selected to delete that one cookie. Figure 4. Deleting a selected cookie Click Clear All to delete all cookies. Figure 5. Clearing all cookies Improve article


View and edit local storage

This guide shows you how to use Chrome DevTools to view, edit, and delete localStorage key-value pairs.

View localStorage keys and values

Click the Application tab to open the Application panel. Expand the Local Storage menu. Figure 4. Viewing the value of the yt-remote-connected-devices key

Create a new localStorage key-value pair

View a domain's localStorage key-value pairs. Double-click the empty part of the table. DevTools creates a new row and focuses your cursor in the Key column. Figure 5. The empty part of the table to double-click in order to create a new key-value pair

Edit localStorage keys or values

View a domain's localStorage key-value pairs. Double-click a cell in the Key or Value column to edit that key or value. Figure 6. Editing a localStorage key

Delete localStorage key-value pairs

View a domain's localStorage key-value pairs. Click the key-value pair that you want to delete. DevTools highlights it blue to indicate that it's selected. Press the Delete key or click Delete Selected .

Delete all localStorage key-value pairs for a domain

View a domain's localStorage key-value pairs. Click Clear All .

Interact with localStorage from the Console

Since you can run JavaScript in the Console, and since the Console has access to the page's JavaScript contexts, it's possible to interact with localStorage from the Console. Use the JavaScript contexts menu to change the JavaScript context of the Console if you want to access the localStorage key-value pairs of a domain other than the page you're on. Figure 7. Changing the JavaScript context of the Console Run your localStorage expressions in the Console, the same as you would in your JavaScript. Figure 8. Interacting with localStorage from the Console Improve article


View and change IndexedDB data

This guide shows you how to use Chrome DevTools to view and change IndexedDB data. It assumes you're familiar with DevTools. If not, see Get started. It also assumes you're familiar with IndexedDB. If not, see Using IndexedDB.

View IndexedDB data

Click the Application tab to open the Application panel. Expand the IndexedDB menu to see which databases are available. Figure 1. The IndexedDB menu notes is an object store. title and body are indexes. Known Limitation Third-party databases are not visible. For example, if you use an <iframe> to embed an ad on your page, and your ad network uses IndexedDB, your ad network's IndexedDB data won't be visible. See issue #943770. Click a database to see its origin and version number. Figure 2. The notes database Click an object store to see its key-value pairs. Caution IndexedDB data does not update in real-time. See Refresh IndexedDB data. Figure 3. The notes object store Total entries is the total number of key-value pairs in the object store. Key generator value is the next available key. This field is only shown when using key generators. Click a cell in the Value column to expand that value. Figure 4. Viewing an IndexedDB value Click an index, such as title or body in Figure 6 below, to sort the object store according to the values of that index. Figure 5. An object store that is sorted alphabetically according to its title key

Refresh IndexedDB data

IndexedDB values in the Application panel do not update in real-time. Click Refresh when viewing an object store to refresh its data, or view a database and click Refresh database to refresh all data. Figure 6. Viewing a database

Edit IndexedDB data

IndexedDB keys and values are not editable from the Application panel. Since DevTools has access to page context, however, you can run JavaScript code within DevTools that edits IndexedDB data.

 Edit IndexedDB data with Snippets

Run Snippets of JavaScript are a way to store and run blocks of JavaScript code within DevTools. When you run a Snippet, the result is logged to the Console. You can use a Snippet to run JavaScript code that edits an IndexedDB database. Figure 7. Using a Snippet to interact with IndexedDB

Delete IndexedDB data

 Delete an IndexedDB key-value pair

View an IndexedDB object store. Click the key-value pair that you want to delete. DevTools highlights it blue to indicate that it's selected. Figure 8. Selecting a key-value pair in order to delete it Press the Delete key or click Delete Selected . Figure 9. How the object store looks after the key-value pair has been deleted

 Delete all key-value pairs in an object store

View an IndexedDB object store. Figure 10. Viewing an object store Click Clear object store .

 Delete an IndexedDB database

View the IndexedDB database that you want to delete. Click Delete database. Figure 11. The Delete database button

 Delete all IndexedDB storage

Open the Clear storage pane. Make sure that the IndexedDB checkbox is enabled. Click Clear site data. Figure 12. The Clear storage pane Improve article


View and edit session storage

This guide shows you how to use Chrome DevTools to view, edit, and delete sessionStorage key-value pairs.

View sessionStorage keys and values

Click the Application tab to open the Application panel. Expand the Session Storage menu. Figure 3. Viewing the value of the yt-remote-cast-available key

Create a new sessionStorage key-value pair

View a domain's sessionStorage key-value pairs. Double-click the empty part of the table. DevTools creates a new row and focuses your cursor in the Key column. Figure 4. The empty part of the table to double-click in order to create a new key-value pair

Edit sessionStorage keys or values

View a domain's sessionStorage key-value pairs. Double-click a cell in the Key or Value column to edit that key or value. Figure 5. Editing a sessionStorage key

Delete sessionStorage key-value pairs

View a domain's sessionStorage key-value pairs. Click the key-value pair that you want to delete. DevTools highlights it blue to indicate that it's selected. Press the Delete key or click Delete Selected .

Delete all sessionStorage key-value pairs for a domain

View a domain's sessionStorage key-value pairs. Click Clear All .

Interact with sessionStorage from the Console

Since you can run JavaScript in the Console, and since the Console has access to the page's JavaScript contexts, it's possible to interact with sessionStorage from the Console. Use the JavaScript contexts menu to change the JavaScript context of the Console if you want to access the sessionStorage key-value pairs of a domain other than the page you're on. Figure 6. Changing the JavaScript context of the Console Run your sessionStorage expressions in the Console, the same as you would in your JavaScript. Figure 7. Interacting with sessionStorage from the Console Improve article


View Application Cache Data With Chrome DevTools

Warning Support for AppCache will be removed from Chrome and other Chromium-based browsers. We encourage developers to migrate off of AppCache now, rather than waiting any longer. Read more. This guide shows you how to use Chrome DevTools to inspect Application Cache resources.

View Application Cache Data

Click the Sources tab to open the Sources panel. The Manifest pane usually opens by default. Expand the Application Cache section and click a cache to view its resources. Each row of the table represents a cached resource. The Type column represents the resource's category: Master. The manifest attribute on the resource indicated that this cache is the resource's master. Explicit. This resource was explicitly listed in the manifest. Network. The manifest specified that this resource must come from the network. Fallback. The URL is a fallback for another resource. The URL of the other resource is not listed in DevTools. At the bottom of the table there are status icons indicating your network connection and the status of the Application Cache. The Application Cache can have the following statuses: IDLE. The cache has no new changes. CHECKING. The manifest is being fetched and checked for updates. DOWNLOADING. Resources are being added to the cache. UPDATEREADY. A new version of the cache is available. OBSOLETE. The cache is being deleted. Improve article


View Web SQL data

Warning The Web SQL specification is not being maintained and does not have cross-browser support. This guide shows you how to use Chrome DevTools to inspect Web SQL data.

View Web SQL Data

Click the Sources tab to open the Application panel. Expand the Web SQL section to view databases and tables. In Figure 1 below html5meetup is a database and rooms is a table. Figure 1. The Web SQL pane. Click a table to view that table's data. Figure 2. Viewing the data of the rooms Web SQL table.

Edit Web SQL data

You can't edit Web SQL data when viewing a Web SQL table, such as in Figure 2 above. But you can run statements from the Web SQL Console that edit or delete tables. See Run Web SQL queries.

Run Web SQL queries

Click a database to open a console for that database. Type a Web SQL statement, then press Enter to run it. Figure 3. Using the Web SQL Console to delete a row from the rooms table.

Refresh a Web SQL table

DevTools does not update tables in real-time. To update the data in a table: View a Web SQL table's data. Click Refresh .

Filter out columns in a Web SQL table

View a Web SQL table's data. Use the Visible columns text box to specify what columns you want to show. Provide the column names as a CSV list. Figure 4. Using the Visible Columns text box to only show the room_name and last_updated columns.

Delete all Web SQL data

Open the Clear Storage pane. Make sure that the Web SQL checkbox is enabled. Figure 5. The Web SQL checkbox. Click Clear site data. Figure 6. The Clear Site Data button. Improve article


View Cache data

This guide shows you how to use Chrome DevTools to inspect Cache data. If you're trying to inspect HTTP cache data, this is not the guide you want. The Size column of the Network Log has the information you're looking for. See Log network activity.

View cache data

Click the Application tab to open the Application panel. Expand the Cache Storage section to view available caches. Figure 1. Available caches. Click a cache to view its contents. Figure 2. Viewing the airhorner-0.6.11 cache. Click a resource to view its HTTP headers in the section below the table. Figure 3. Viewing the HTTP headers of the /index.html resource. Click Preview to view a resource's content. Figure 4. Viewing the content of the /scripts.comlink.global.js resource.

Refresh a resource

View a cache's data. Click the resource that you want to refresh. DevTools highlights it blue to indicate that it's selected. Figure 5. Selecting the /styles/main.css resource. Click Refresh .

Filter resources

View a cache's data. Use the Filter by Path text box to filter out any resources that do not match the path that you provide. Figure 6. Filtering out resources that do not match the /script path.

Delete a resource

View a cache's data. Click the resource that you want to delete. DevTools highlights it blue to indicate that it's selected. Figure 7. Selecting the /styles/main.css resource. Click Delete Selected .

Delete all cache data

Open Application > Clear Storage. Make sure that the Cache Storage checkbox is enabled. Figure 8. The Cache Storage checkbox. Click Clear site data. Figure 9. The Clear Site Data button. Improve article


Find and fix problems with the Issues tab

The Issues tab in Chrome DevTools reduces the notification fatigue and clutter of the Console. Use it to find solutions to problems detected by the browser, such as cookie issues and mixed content. In Chrome 84, the Issues tab supports three types of issue: Cookie problems Mixed content COEP issues Future versions of Chrome will support more issue types.

Open the Issues tab

Visit a page with issues to fix, such as samesite-sandbox.glitch.me. Open DevTools. Click the Go to Issues button in the yellow warning bar. Alternatively, select Issues from the More tools menu. Once you're on the Issues tab, click the Reload page button if necessary. You'll notice that issues reported in the Console (such as the cookie warnings here) are quite hard to understand. It's not clear what needs to be done to fix the issues reported.

View items in the Issues tab

The Issues tab presents warnings from the browser in a structured, aggregated, and actionable way. Click an item in the Issues tab to get guidance on how to fix the issue and find affected resources. Each item has four components: A headline describing the issue. A description providing the context and the solution. An AFFECTED RESOURCES section that links to resources within the appropriate DevTools context, such as the Network panel. Links to further guidance. Click on AFFECTED RESOURCES items to view details. In this example, there is one cookie and one request affected.

View issues in context

Click on a resource link to view the item in the appropriate context within DevTools. In this example, click samesite-sandbox.glitch.me to show the cookies attached to that request. Scroll to view the item with a problem: in this case, the cookie ck02. Hover over the information icon on the right to see the problem and how to fix it. Improve article


Run commands in the Command Menu

The Command Menu provides a fast way to navigate the Chrome DevTools UI and accomplish common tasks, such as disabling JavaScript. You may be familiar with a similar feature in Visual Studio Code called the Command Palette, which was the original inspiration for the Command Menu. Figure 1. Using the Command Menu to disable JavaScript.

Open the Command Menu

Press Control+Shift+P or Command+Shift+P (Mac). Or, click Customize And Control DevTools and then select Run Command. Figure 2. Run Command.

See other available actions

If you use the workflow outlined in Open the Command Menu, the Command Menu opens with a > character prepended to the Command Menu text box. Figure 3. The command character. Delete the > character and type ? to see other actions that are available from the Command Menu. Figure 4. Other available actions. Improve article


Simulate mobile devices with Device Mode

Use Device Mode to approximate how your page looks and performs on a mobile device. Device Mode is the name for the loose collection of features in Chrome DevTools that help you simulate mobile devices. These features include: Simulating a mobile viewport Throttling the network Throttling the CPU Simulating geolocation Setting orientation

Limitations

Think of Device Mode as a first-order approximation of how your page looks and feels on a mobile device. With Device Mode you don't actually run your code on a mobile device. You simulate the mobile user experience from your laptop or desktop. There are some aspects of mobile devices that DevTools will never be able to simulate. For example, the architecture of mobile CPUs is very different than the architecture of laptop or desktop CPUs. When in doubt, your best bet is to actually run your page on a mobile device. Use Remote Debugging to view, change, debug, and profile a page's code from your laptop or desktop while it actually runs on a mobile device.

Simulate a mobile viewport

Click Toggle Device Toolbar to open the UI that enables you to simulate a mobile viewport. Figure 1. The Device Toolbar By default the Device Toolbar opens in Responsive Viewport Mode.

 Responsive Viewport Mode

Drag the handles to resize the viewport to whatever dimensions you need. Or, enter specific values in the width and height boxes. In Figure 2, the width is set to 628 and the height is set to 662. Figure 2. The handles for changing the viewport's dimensions when in Responsive Viewport Mode

Show media queries

To show media query breakpoints above your viewport, click More options and then select Show media queries. Figure 3. Show media queries Click a breakpoint to change the viewport's width so that the breakpoint gets triggered. Figure 4. Click a breakpoint to change the viewport's width

Set the device type

Use the Device Type list to simulate a mobile device or desktop device. Figure 5. The Device Type list The table below describes the differences between the options. Rendering method refers to whether Chrome renders the page as a mobile or desktop viewport. Cursor icon refers to what type of cursor you see when you hover over the page. Events fired refers to whether the page fires touch or click events when you interact with the page.
Option Rendering method Cursor icon Events fired
MobileMobileCircle touch
Mobile (no touch)MobileNormal click
DesktopDesktopNormal click
Desktop (touch)DesktopCircle touch

 Mobile Device Viewport Mode

To simulate the dimensions of a specific mobile device, select the device from the Device list. Figure 6. The Device list

Rotate the viewport to landscape orientation

Click Rotate to rotate the viewport to landscape orientation. Figure 7. Landscape orientation Note that the Rotate button disappears if your Device Toolbar is narrow. Figure 8. The Device Toolbar See also Set orientation.

Show device frame

When simulating the dimensions of a specific mobile device like an iPhone 6, open More options and then select Show device frame to show the physical device frame around the viewport. Note: If you don't see a device frame for a particular device, it probably means that DevTools just doesn't have art for that specific option. Figure 9. Show device frame Figure 10. The device frame for the iPhone 6

Add a custom mobile device

To add a custom device: Click the Device list and then select Edit. Figure 11. Selecting Edit Click Add custom device. Enter a name, width, and height for the device. The device pixel ratio, user agent string, and device type fields are optional. The device type field is the list that is set to Mobile by default. Figure 12. Creating a custom device

 Show rulers

Click More options and then select Show rulers to see rulers above and to the left of your viewport. The sizing unit of the rulers is pixels. Figure 13. Show rulers Figure 14. Rulers above and to the left of the viewport

 Zoom the viewport

Use the Zoom list to zoom in or out. Figure 15. Zoom

Throttle the network and CPU

To throttle the network and CPU, select Mid-tier mobile or Low-end mobile from the Throttle list. Figure 16. The Throttle list Mid-tier mobile simulates fast 3G and throttles your CPU so that it is 4 times slower than normal. Low-end mobile simulates slow 3G and throttles your CPU 6 times slower than normal. Keep in mind that the throttling is relative to the normal capability of your laptop or desktop. Note that the Throttle list will be hidden if your Device Toolbar is narrow. Figure 17. The Device Toolbar

 Throttle the CPU only

To throttle the CPU only and not the network, go to the Performance panel, click Capture Settings , and then select 4x slowdown or 6x slowdown from the CPU list. Figure 18. The CPU list

 Throttle the network only

To throttle the network only and not the CPU, go the Network panel and select Fast 3G or Slow 3G from the Throttle list. Figure 19. The Throttle list Or press Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux, Chrome OS) to open the Command Menu, type 3G, and select Enable fast 3G throttling or Enable slow 3G throttling. Figure 20. The Command Menu You can also set network throttling from the Performance panel. Click Capture Settings Capture Settings and then select Fast 3G or Slow 3G from the Network list. Figure 21. Setting network throttling from the Performance panel

Override geolocation

To open the geolocation overriding UI click Customize and control DevTools and then select More tools > Sensors. Figure 22. Sensors Or press Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux, Chrome OS) to open the Command Menu, type Sensors, and then select Show Sensors. Figure 23. Show Sensors Select one of the presets from the Location list, or select Other... to enter your own coordinates, or select Location unavailable to test out how your page behaves when geolocation is in an error state. Figure 24. Geolocation

Set orientation

To open the orientation UI click Customize and control DevTools and then select More tools > Sensors. Figure 25. Sensors Or press Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux, Chrome OS) to open the Command Menu, type Sensors, and then select Show Sensors. Figure 26. Show Sensors Select one of the presets from the Orientation list or select Custom orientation to set your own alpha, beta, and gamma values. Figure 27. Orientation Improve article


Override the user agent string

To override the user agent string from Chrome DevTools: Press Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux, Chrome OS) to open the Command Menu. Figure 1. The Command Menu Type network conditions, select Show Network conditions, and press Enter to open the Network conditions tab. In the User agent section disable the Select automatically checkbox. Figure 2. Disabling Select automatically Select a user agent string from the list, or enter your own custom string. Improve article


Override geolocation

Many websites take advantage of user location in order to provide a more relevant experience for their users. For example, a weather website might show the local forecast for a user's area, once the user has granted the website permission to access their location. If you're building a UI that changes depending on where the user is located, you probably want to make sure that the site behaves correctly in different places around the world. To override your geolocation in Chrome DevTools: Press Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux, Chrome OS) to open the Command Menu. Figure 1. The Command Menu Type sensors, select Show Sensors, and press Enter. The Sensors tab opens up at the bottom of your DevTools window. From the Geolocation list select one of the preset cities, like Tokyo, or select Custom location to enter custom longitude and latitude coordinates, or select Location unavailable to see how your site behaves when the user's location is not available. Figure 2. Selecting Tokyo from the Geolocation list Improve article


Simulate device orientation

To simulate different device orientations from Chrome DevTools: Press Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux, Chrome OS) to open the Command Menu. Figure 1. The Command Menu Type sensors, select Show Sensors, and press Enter. The Sensors tab opens up at the bottom of your DevTools window. From the Orientation list select one of the preset orientations, like Portrait upside down, or select Custom orientation to provide your own exact orientation. Figure 2. Selecting Portrait upside down from the Orientation list After selecting Custom orientation the alpha, beta, and gamma fields are enabled. See Alpha, Beta, and Gamma to understand how these axes work. You can also set a custom orientation by dragging the Orientation Model. Hold Shift before dragging to rotate along the alpha axis. Figure 3. The Orientation Model Improve article


Debug JavaScript

This tutorial teaches you the basic workflow for debugging any JavaScript issue in DevTools. Read on, or watch the video version of this tutorial, below.

Step 1: Reproduce the bug

Finding a series of actions that consistently reproduces a bug is always the first step to debugging. Click Open Demo. The demo opens in a new tab. Open Demo Enter 5 in the Number 1 text box. Enter 1 in the Number 2 text box. Click Add Number 1 and Number 2. The label below the button says 5 + 1 = 51. The result should be 6. This is the bug you're going to fix. Figure 1. The result of 5 + 1 is 51. It should be 6.

Step 2: Get familiar with the Sources panel UI

DevTools provides a lot of different tools for different tasks, such as changing CSS, profiling page load performance, and monitoring network requests. The Sources panel is where you debug JavaScript. Open DevTools by pressing Command+Option+I (Mac) or Control+Shift+I (Windows, Linux). This shortcut opens the Console panel. Figure 2. The Console panel Click the Sources tab. Figure 3. The Sources panel The Sources panel UI has 3 parts: Figure 4. The 3 parts of the Sources panel UI The File Navigator pane. Every file that the page requests is listed here. The Code Editor pane. After selecting a file in the File Navigator pane, the contents of that file are displayed here. The JavaScript Debugging pane. Various tools for inspecting the page's JavaScript. If your DevTools window is wide, this pane is displayed to the right of the Code Editor pane.

Step 3: Pause the code with a breakpoint

A common method for debugging a problem like this is to insert a lot of console.log() statements into the code, in order to inspect values as the script executes. For example: function updateLabel() {
var addend1 = getNumber1();
console.log('addend1:', addend1);
var addend2 = getNumber2();
console.log('addend2:', addend2);
var sum = addend1 + addend2;
console.log('sum:', sum);
label.textContent = addend1 + ' + ' + addend2 + ' = ' + sum;
}
The console.log() method may get the job done, but breakpoints can get it done faster. A breakpoint lets you pause your code in the middle of its execution, and examine all values at that moment in time. Breakpoints have a few advantages over the console.log() method: With console.log(), you need to manually open the source code, find the relevant code, insert the console.log() statements, and then reload the page in order to see the messages in the Console. With breakpoints, you can pause on the relevant code without even knowing how the code is structured. In your console.log() statements you need to explicitly specify each value that you want to inspect. With breakpoints, DevTools shows you the values of all variables at that moment in time. Sometimes there are variables affecting your code that you're not even aware of. In short, breakpoints can help you find and fix bugs faster than the console.log() method. If you take a step back and think about how the app works, you can make an educated guess that the incorrect sum (5 + 1 = 51) gets computed in the click event listener that's associated to the Add Number 1 and Number 2 button. Therefore, you probably want to pause the code around the time that the click listener executes. Event Listener Breakpoints let you do exactly that: In the JavaScript Debugging pane, click Event Listener Breakpoints to expand the section. DevTools reveals a list of expandable event categories, such as Animation and Clipboard. Next to the Mouse event category, click Expand . DevTools reveals a list of mouse events, such as click and mousedown. Each event has a checkbox next to it. Check the click checkbox. DevTools is now set up to automatically pause when any click event listener executes. Figure 5. The click checkbox is enabled Back on the demo, click Add Number 1 and Number 2 again. DevTools pauses the demo and highlights a line of code in the Sources panel. DevTools should be paused on this line of code: function onClick() { If you're paused on a different line of code, press Resume Script Execution until you're paused on the correct line. Note: If you paused on a different line, you have a browser extension that registers a click event listener on every page that you visit. You were paused in the extension's click listener. If you use Incognito Mode to browse in private, which disables all extensions, you can see that you pause on the correct line of code every time. Event Listener Breakpoints are just one of many types of breakpoints available in DevTools. It's worth memorizing all the different types, because each type ultimately helps you debug different scenarios as quickly as possible. See Pause Your Code With Breakpoints to learn when and how to use each type.

Step 4: Step through the code

One common cause of bugs is when a script executes in the wrong order. Stepping through your code enables you to walk through your code's execution, one line at a time, and figure out exactly where it's executing in a different order than you expected. Try it now: On the Sources panel of DevTools, click Step into next function call to step through the execution of the onClick() function, one line at a time. DevTools highlights the following line of code: if (inputsAreEmpty()) { Click Step over next function call . DevTools executes inputsAreEmpty() without stepping into it. Notice how DevTools skips a few lines of code. This is because inputsAreEmpty() evaluated to false, so the if statement's block of code didn't execute. That's the basic idea of stepping through code. If you look at the code in get-started.js, you can see that the bug is probably somewhere in the updateLabel() function. Rather than stepping through every line of code, you can use another type of breakpoint to pause the code closer to the probable location of the bug.

Step 5: Set a line-of-code breakpoint

Line-of-code breakpoints are the most common type of breakpoint. When you've got a specific line of code that you want to pause on, use a line-of-code breakpoint: Look at the last line of code in updateLabel(): label.textContent = addend1 + ' + ' + addend2 + ' = ' + sum; To the left of the code you can see the line number of this particular line of code, which is 32. Click on 32. DevTools puts a blue icon on top of 32. This means that there is a line-of-code breakpoint on this line. DevTools now always pauses before this line of code is executed. Click Resume script execution . The script continues executing until it reaches line 32. On lines 29, 30, and 31, DevTools prints out the values of addend1, addend2, and sum to the right of each line's semi-colon. Figure 6. DevTools pauses on the line-of-code breakpoint on line 32

Step 6: Check variable values

The values of addend1, addend2, and sum look suspicious. They're wrapped in quotes, which means that they're strings. This is a good hypothesis for the explaining the cause of the bug. Now it's time to gather more information. DevTools provides a lot of tools for examining variable values.

 Method 1: The Scope pane

When you're paused on a line of code, the Scope pane shows you what local and global variables are currently defined, along with the value of each variable. It also shows closure variables, when applicable. Double-click a variable value to edit it. When you're not paused on a line of code, the Scope pane is empty. Figure 7. The Scope pane

 Method 2: Watch Expressions

The Watch Expressions tab lets you monitor the values of variables over time. As the name implies, Watch Expressions aren't just limited to variables. You can store any valid JavaScript expression in a Watch Expression. Try it now: Click the Watch tab. Click Add Expression . Type typeof sum. Press Enter. DevTools shows typeof sum: "string". The value to the right of the colon is the result of your Watch Expression. Figure 8. The Watch Expression pane (bottom-right), after creating the typeof sum Watch Expression. If your DevTools window is large, the Watch Expression pane is on the right, above the Event Listener Breakpoints pane. As suspected, sum is being evaluated as a string, when it should be a number. You've now confirmed that this is the cause of the bug.

 Method 3: The Console

In addition to viewing console.log() messages, you can also use the Console to evaluate arbitrary JavaScript statements. In terms of debugging, you can use the Console to test out potential fixes for bugs. Try it now: If you don't have the Console drawer open, press Escape to open it. It opens at the bottom of your DevTools window. In the Console, type parseInt(addend1) + parseInt(addend2). This statement works because you are paused on a line of code where addend1 and addend2 are in scope. Press Enter. DevTools evaluates the statement and prints out 6, which is the result you expect the demo to produce. Figure 9. The Console drawer, after evaluating parseInt(addend1) + parseInt(addend2).

Step 7: Apply a fix

You've found a fix for the bug. All that's left is to try out your fix by editing the code and re-running the demo. You don't need to leave DevTools to apply the fix. You can edit JavaScript code directly within the DevTools UI. Try it now: Click Resume script execution . In the Code Editor, replace line 31, var sum = addend1 + addend2, with var sum = parseInt(addend1) + parseInt(addend2). Press Command+S (Mac) or Control+S (Windows, Linux) to save your change. Click Deactivate breakpoints . It changes blue to indicate that it's active. While this is set, DevTools ignores any breakpoints you've set. Try out the demo with different values. The demo now calculates correctly. Caution Caution: This workflow only applies a fix to the code that is running in your browser. It won't fix the code for all users that visit your page. To do that, you need to fix the code that's on your servers.

Next steps

Congratulations! You now know how to make the most of Chrome DevTools when debugging JavaScript. The tools and methods you learned in this tutorial can save you countless hours. This tutorial only showed you two ways to set breakpoints. DevTools offers many other ways, including: Conditional breakpoints that are only triggered when the condition that you provide is true. Breakpoints on caught or uncaught exceptions. XHR breakpoints that are triggered when the requested URL matches a substring that you provide. See Pause Your Code With Breakpoints to learn when and how to use each type. There's a couple of code stepping controls that weren't explained in this tutorial. See Step over line of code to learn more. Improve article


Pause your code with breakpoints

Use breakpoints to pause your JavaScript code. This guide explains each type of breakpoint that's available in DevTools, as well as when to use and how to set each type. For a hands-on tutorial of the debugging process, see Debugging JavaScript.

Overview of when to use each breakpoint type

The most well-known type of breakpoint is line-of-code. But line-of-code breakpoints can be inefficient to set, especially if you don't know exactly where to look, or if you are working with a large codebase. You can save yourself time when debugging by knowing how and when to use the other types of breakpoints.
Breakpoint Type Use This When You Want To Pause...
Line-of-codeOn an exact region of code.
Conditional line-of-code On an exact region of code, but only when some other condition is true.
DOMOn the code that changes or removes a specific DOM node, or its children.
XHRWhen an XHR URL contains a string pattern.
Event listener On the code that runs after an event, such as click, is fired.
ExceptionOn the line of code that is throwing a caught or uncaught exception.
FunctionWhenever a specific function is called.

Line-of-code breakpoints

Use a line-of-code breakpoint when you know the exact region of code that you need to investigate. DevTools always pauses before this line of code is executed. To set a line-of-code breakpoint in DevTools: Click the Sources tab. Open the file containing the line of code you want to break on. Go the line of code. To the left of the line of code is the line number column. Click on it. A blue icon appears on top of the line number column. Figure 1: A line-of-code breakpoint set on line 29

 Line-of-code breakpoints in your code

Call debugger from your code to pause on that line. This is equivalent to a line-of-code breakpoint, except that the breakpoint is set in your code, not in the DevTools UI. console.log('a');
console.log('b');
debugger;
console.log('c');

 Conditional line-of-code breakpoints

Use a conditional line-of-code breakpoint when you know the exact region of code that you need to investigate, but you want to pause only when some other condition is true. To set a conditional line-of-code breakpoint: Click the Sources tab. Open the file containing the line of code you want to break on. Go the line of code. To the left of the line of code is the line number column. Right-click it. Select Add conditional breakpoint. A dialog displays underneath the line of code. Enter your condition in the dialog. Press Enter to activate the breakpoint. An orange icon appears on top of the line number column. Figure 2: A conditional line-of-code breakpoint set on line 32

 Manage line-of-code breakpoints

Use the Breakpoints pane to disable or remove line-of-code breakpoints from a single location. Figure 3: The Breakpoints pane showing two line-of-code breakpoints: one on line 15 of get-started.js, another on line 32 Check the checkbox next to an entry to disable that breakpoint. Right-click an entry to remove that breakpoint. Right-click anywhere in the Breakpoints pane to deactivate all breakpoints, disable all breakpoints, or remove all breakpoints. Disabling all breakpoints is equivalent to unchecking each one. Deactivating all breakpoints instructs DevTools to ignore all line-of-code breakpoints, but to also maintain preserve their enabled state so that they are in the same state as before when you reactivate them. Figure 4: Deactivated breakpoints in the Breakpoints pane are disabled and transparent

DOM change breakpoints

Use a DOM change breakpoint when you want to pause on the code that changes a DOM node or its children. To set a DOM change breakpoint: Click the Elements tab. Go the element that you want to set the breakpoint on. Right-click the element. Hover over Break on then select Subtree modifications, Attribute modifications, or Node removal. Figure 5: The context menu for creating a DOM change breakpoint

 Types of DOM change breakpoints

Subtree modifications. Triggered when a child of the currently-selected node is removed or added, or the contents of a child are changed. Not triggered on child node attribute changes, or on any changes to the currently-selected node. Attributes modifications: Triggered when an attribute is added or removed on the currently-selected node, or when an attribute value changes. Node Removal: Triggered when the currently-selected node is removed.

XHR/Fetch breakpoints

Use an XHR breakpoint when you want to break when the request URL of an XHR contains a specified string. DevTools pauses on the line of code where the XHR calls send(). Note: This feature also works with Fetch requests. One example of when this is helpful is when you see that your page is requesting an incorrect URL, and you want to quickly find the AJAX or Fetch source code that is causing the incorrect request. To set an XHR breakpoint: Click the Sources tab. Expand the XHR Breakpoints pane. Click Add breakpoint. Enter the string which you want to break on. DevTools pauses when this string is present anywhere in an XHR's request URL. Press Enter to confirm. Figure 6: Creating an XHR breakpoint in the XHR Breakpoints for any request that contains org in the URL

Event listener breakpoints

Use event listener breakpoints when you want to pause on the event listener code that runs after an event is fired. You can select specific events, such as click, or categories of events, such as all mouse events. Click the Sources tab. Expand the Event Listener Breakpoints pane. DevTools shows a list of event categories, such as Animation. Check one of these categories to pause whenever any event from that category is fired, or expand the category and check a specific event. Figure 7: Creating an event listener breakpoint for deviceorientation

Exception breakpoints

Use exception breakpoints when you want to pause on the line of code that's throwing a caught or uncaught exception. Click the Sources tab. Click Pause on exceptions . It turns blue when enabled. **Figure 8**: The **Pause on exceptions** button (Optional) Check the Pause On Caught Exceptions checkbox if you also want to pause on caught exceptions, in addition to uncaught ones. Figure 9: Paused on an uncaught exception

Function breakpoints

Call debug(functionName), where functionName is the function you want to debug, when you want to pause whenever a specific function is called. You can insert debug() into your code (like a console.log() statement) or call it from the DevTools Console. debug() is equivalent to setting a line-of-code breakpoint on the first line of the function. function sum(a, b) {
let result = a + b; // DevTools pauses on this line.
return result;
}
debug(sum); // Pass the function object, not a string.
sum();

 Make sure the target function is in scope

DevTools throws a ReferenceError if the function you want to debug is not in scope. (function () {
function hey() {
console.log('hey');
}
function yo() {
console.log('yo');
}
debug(yo); // This works.
yo();
})();
debug(hey); // This doesn't work. hey() is out of scope.
Ensuring the target function is in scope can be tricky if you're calling debug() from the DevTools Console. Here's one strategy: Set a line-of-code breakpoint somewhere where the function is in scope. Trigger the breakpoint. Call debug() in the DevTools Console while the code is still paused on your line-of-code breakpoint. Improve article


JavaScript debugging reference

Discover new debugging workflows with this comprehensive reference of Chrome DevTools debugging features. See Debugging JavaScript to learn the basics of debugging.

Pause code with breakpoints

Set a breakpoint so that you can pause your code in the middle of its execution. See Pause Your Code With Breakpoints to learn how to set breakpoints.

Step through code

Once your code is paused, step through it, one line at a time, investigating control flow and property values along the way.

 Step over line of code

When paused on a line of code containing a function that's not relevant to the problem you're debugging, click Step over to execute the function without stepping into it. Figure 1. Step over, outlined in blue For example, suppose you're debugging the following code: function updateHeader() {
var day = new Date().getDay();
var name = getName(); // A
updateName(name); // D
}
function getName() {
var name = app.first + ' ' + app.last; // B
return name; // C
}
You're paused on A. By pressing Step over, DevTools executes all the code in the function that you're stepping over, which is B and C. DevTools then pauses on D.

 Step into line of code

When paused on a line of code containing a function call that is related to the problem you're debugging, click Step into to investigate that function further. Figure 2. Step into, outlined in blue For example, suppose you're debugging the following code: function updateHeader() {
var day = new Date().getDay();
var name = getName(); // A
updateName(name);
}
function getName() {
var name = app.first + ' ' + app.last; // B
return name;
}
You're paused on A. By pressing Step into, DevTools executes this line of code, then pauses on B.

 Step out of line of code

When paused inside of a function that is not related to the problem you're debugging, click Step out to execute the rest of the function's code. Figure 3. Step out, outlined in blue For example, suppose you're debugging the following code: function updateHeader() {
var day = new Date().getDay();
var name = getName();
updateName(name); // C
}
function getName() {
var name = app.first + ' ' + app.last; // A
return name; // B
}
You're paused on A. By pressing Step out, DevTools executes the rest of the code in getName(), which is just B in this example, and then pauses on C.

 Run all code up to a certain line

When debugging a long function, there may be a lot of code that is not related to the problem you're debugging. You could step through all the lines, but that can be tedious. You could set a line-of-code breakpoint on the line you're interested in and then press Resume Script Execution , but there's a faster way. Right-click the line of code that you're interested in, and select Continue to here. DevTools runs all of the code up to that point, and then pauses on that line. Figure 4. Selecting Continue to here

 Resume script execution

To continue your script's execution after a pause, click Resume Script Execution . DevTools executes the script up until the next breakpoint, if any. Figure 6. Resume script execution, outlined in blue

Force script execution

To ignore all breakpoints and force your script to resume execution, click and hold Resume Script Execution . Figure 7. Selecting Force script execution

 Change thread context

When working with web workers or service workers, click on a context listed in the Threads pane to switch to that context. The blue arrow icon represents which context is currently selected. Figure 8. The Threads pane, outlined in blue For example, suppose that you're paused on a breakpoint in both your main script and your service worker script. You want to view the local and global properties for the service worker context, but the Sources panel is showing the main script context. By clicking on the service worker entry in the Threads pane, you'd be able to switch to that context.

View and edit local, closure, and global properties

While paused on a line of code, use the Scope pane to view and edit the values of properties and variables in the local, closure, and global scopes. Double-click a property value to change it. Non-enumerable properties are greyed out. Figure 9. The Scope pane, outlined in blue

View the current call stack

While paused on a line of code, use the Call Stack pane to view the call stack that got you to this point. If you're working with async code, check the Async checkbox to enable async call stacks. Click on an entry to jump to the line of code where that function was called. The blue arrow icon represents which function DevTools is currently highlighting. Figure 10. The Call Stack pane, outlined in blue Note: When not paused on a line of code, the Call Stack pane is empty.

 Copy stack trace

Right-click anywhere in the Call Stack pane and select Copy stack trace to copy the current call stack to the clipboard. Figure 11. Selecting Copy Stack Trace Below is an example of the output: getNumber1 (get-started.js:35)
inputsAreEmpty (get-started.js:22)
onClick (get-started.js:15)

Ignore a script or pattern of scripts

Ignore a script to skip it while debugging. When ignored, a script is obscured in the Call Stack pane, and you never step into the script's functions when you step through your code. For example, suppose you're stepping through this code: function animate() {
prepare();
lib.doFancyStuff(); // A
render();
}
A is a third-party library that you trust. If you're confident that the problem you're debugging is not related to the third-party library, then it makes sense to ignore the script.

 Ignore a script from the Editor pane

To ignore a script from the Editor pane: Open the file. Right-click anywhere. Select Add script to ignore list. Figure 12. Ignoring a script from the Editor pane

 Ignore a script from the Call Stack pane

To ignore a script from the Call Stack pane: Right-click on a function from the script. Select Add script to ignore list. Figure 13. Ignoring a script from the Call Stack pane

 Ignore a script from Settings

To ignore a single script or pattern of scripts from Settings: Open Settings. Go to the Ignore List tab. Click Add pattern. Enter the script name or a regex pattern of script names to ignore. Click Add. Figure 14. Ignoring a script from Settings

Run snippets of debug code from any page

If you find yourself running the same debug code in the Console over and over, consider Snippets. Snippets are executable scripts that you author, store, and run within DevTools. See Run Snippets of Code From Any Page to learn more.

Watch the values of custom JavaScript expressions

Use the Watch pane to watch the values of custom expressions. You can watch any valid JavaScript expression. Figure 15. The Watch pane, outlined in blue Click Add Expression to create a new watch expression. Click Refresh to refresh the values of all existing expressions. Values automatically refresh while stepping through code. Hover over an expression and click Delete Expression to delete it.

Make a minified file readable

Click Format to make a minified file human-readable. Figure 16. Format, outlined in blue

Edit a script

When fixing a bug, you often want to test out some changes to your JavaScript code. You don't need to make the changes in an external browser and then reload the page. You can edit your script in DevTools. To edit a script: Open the file in the Editor pane of the Sources panel. Make your changes in the Editor pane. Press Command+S (Mac) or Ctrl+S (Windows, Linux) to save. DevTools patches the entire JS file into Chrome's JavaScript engine. Figure 17. The Editor pane, outlined in blue

Disable JavaScript

See Disable JavaScript With Chrome DevTools. Improve article


Run Snippets of JavaScript

If you find yourself running the same code in the Console repeatedly, consider saving the code as a Snippet instead. Snippets are scripts that you author in the Sources panel. They have access to the page's JavaScript context, and you can run them on any page. Snippets are an alternative to bookmarklets. Firefox DevTools has a feature similar to Snippets called Scratchpad. For example, Figure 1 shows the DevTools homepage on the left and some Snippet source code on the right. Figure 1. How the page looks before running the Snippet. Here's the Snippet source code from Figure 1: console.log('Hello, Snippets!');
document.body.innerHTML = '';
var p = document.createElement('p');
p.textContent = 'Hello, Snippets!';
document.body.appendChild(p);
Figure 2 shows how the page looks after running the Snippet. The Console Drawer pops up to display the Hello, Snippets! message that the Snippet logs, and the page's content changes completely. Figure 2. How the page looks after running the Snippet.

Open the Snippets pane

The Snippets pane lists your Snippets. When you want to edit a Snippet, you need to open it from the Snippets pane. Figure 3. The Snippets pane.

 Open the Snippets pane with a mouse

Click the Sources tab to open the Sources panel. The Page pane usually opens by default. Figure 4. The Sources panel with the Page pane open on the left. Click the Snippets tab to open the Snippets pane. You might need to click More Tabs in order to access the Snippets option.

 Open the Snippets pane with the Command Menu

Focus your cursor somewhere inside of DevTools. Press Control+Shift+P or Command+Shift+P (Mac) to open the Command Menu. Start typing Snippets, select Show Snippets, and then press Enter to run the command. Figure 5. The Show Snippets command.

Create Snippets

 Create a Snippet through the Sources panel

Open the Snippets pane. Click New snippet. Enter a name for your Snippet then press Enter to save. Figure 6. Naming a Snippet.

 Create a Snippet through the Command Menu

Focus your cursor somewhere inside of DevTools. Press Control+Shift+P or Command+Shift+P (Mac) to open the Command Menu. Start typing Snippet, select Create new snippet, then press Enter to run the command. Figure 7. The command for creating a new Snippet. See Rename Snippets if you'd like to give your new Snippet a custom name.

Edit Snippets

Open the Snippets pane. In the Snippets pane click the name of the Snippet that you want to edit in order to open it in the Code Editor. Figure 8. The Code Editor. Use the Code Editor to add JavaScript to your Snippet. When there's an asterisk next to the name of your Snippet it means you have unsaved code. Press Control+S or Command+S (Mac) to save. Figure 9. An asterisk next to the Snippet name, which indicates unsaved code.

Run Snippets

 Run a Snippet from the Sources panel

Open the Snippets pane. Click the name of the Snippet that you want to run. The Snippet opens in the Code Editor. Click Run Snippet , or press Control+Enter or Command+Enter (Mac).

 Run a Snippet with the Command Menu

Focus your cursor somewhere inside of DevTools. Press Control+O or Command+O (Mac) to open the Command Menu. Type the ! character followed by the name of the Snippet that you want to run. Figure 10. Running a Snippet from the Command Menu. Press Enter to run the Snippet.

Rename Snippets

Open the Snippets pane. Right-click the Snippet name and select Rename.

Delete Snippets

Open the Snippets pane. Right-click the Snippet name and select Remove. Improve article


Sources panel overview

Use the Chrome DevTools Sources panel to: View files. Edit CSS and JavaScript. Create and save Snippets of JavaScript, which you can run on any page. Snippets are similar to bookmarklets. Debug JavaScript. Set up a Workspace, so that changes you make in DevTools get saved to the code on your file system.

View files

Use the Page pane to view all of the resources that the page has loaded. Figure 1. The Page pane How the Page pane is organized: The top-level, such as top in Figure 1, represents an HTML frame. You'll find top on every page that you visit. top represents the main document frame. The second-level, such as developers.google.com in Figure 1, represents an origin. The third-level, fourth-level, and so on, represent directories and resources that were loaded from that origin. For example, in Figure 1 the full path to the resource devsite-googler-button is developers.google.com/_static/19aa27122b/css/devsite-googler-button Click a file in the Page pane to view its contents in the Editor pane. You can view any type of file. For images, you see a preview of the image. Figure 2. Viewing the contents of jquery-bundle.js in the Editor pane

Edit CSS and JavaScript

Use the Editor pane to edit CSS and JavaScript. DevTools updates the page to run your new code. For example, if you edit the background-color of an element, you'll see that change take effect immediately. Figure 3. Editing CSS in the Editor pane to change the background color of an element from blue to red CSS changes take effect immediately, no save needed. For JavaScript changes to take effect, press Command+S (Mac) or Control+S (Windows, Linux). DevTools doesn't re-run a script, so the only JavaScript changes that take effect are those that you make inside of functions. For example, in Figure 4 note how console.log('A') doesn't run, whereas console.log('B') does. If DevTools re-ran the entire script after making the change, then the text A would have been logged to the Console. Figure 4. Editing JavaScript in the Editor pane DevTools erases your CSS and JavaScript changes when you reload the page. See Set up a Workspace to learn how to save the changes to your file system.

Create, save, and run Snippets

Snippets are scripts which you can run on any page. Imagine that you repeatedly type out the following code in the Console, in order to insert the jQuery library into a page, so that you can run jQuery commands from the Console: let script = document.createElement('script');
script.src = 'https://code.jquery.com/jquery-3.2.1.min.js';
script.crossOrigin = 'anonymous';
script.integrity = 'sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=';
document.head.appendChild(script);
Instead, you can save this code in a Snippet and run it with a couple of button clicks, any time you need it. DevTools saves the Snippet to your file system. Figure 5. A Snippet that inserts the jQuery library into a page To run a Snippet: Open the file via the Snippets pane, and click Run . Open the Command Menu, delete the > character, type !, type the name of your Snippet, then press Enter. See Run Snippets of JavaScript to learn more.

Debug JavaScript

Rather than using console.log() to infer where your JavaScript is going wrong, consider using the Chrome DevTools debugging tools, instead. The general idea is to set a breakpoint, which is an intentional stopping place in your code, and then step through your code's execution, one line at a time. As you step through the code, you can view and change the values of all currently-defined properties and variables, run JavaScript in the Console, and more. See Debugging JavaScript to learn the basics of debugging in DevTools. Figure 6. Debugging JavaScript

Set up a Workspace

By default, when you edit a file in the Sources panel, those changes are lost when you reload the page. Workspaces enable you to save the changes that you make in DevTools to your file system. Essentially, this lets you use DevTools as your code editor. See Edit Files With Workspaces to get started. Improve article


Debug background services

The Background Services section of Chrome DevTools is a collection of tools for the JavaScript APIs that enables your website to send and receive updates even when a user does not have your website open. A background service is functionally similar to a background process. Chrome DevTools considers each of the following APIs to be a background service: Background Fetch Background Sync Notifications Push Messages Chrome DevTools can log background service events for 3 days, even when DevTools is not open. This can help you make sure that events are being sent and received as expected. You can also inspect the details of each event. Figure 1. Viewing the details of an event in the Push Messaging pane.

Background Fetch

The Background Fetch API enables a service worker to reliably download large resources, like movies or podcasts, as a background service. To log Background Fetch event for 3 days, even when DevTools is not open: Open DevTools. Open the Application panel. Open the Background Fetch pane. Figure 2. The Background Fetch pane. Click Record . After triggering some Background Fetch activity, DevTools logs the events to the table. Figure 3. A log of events in the Background Fetch pane. Click an event to view its details in the space below the table. Figure 4. Viewing the details of an event in the Background Fetch pane.

Background Sync

The Background Sync API enables an offline service worker to send data to a server once it has re-established a reliable internet connection. To log Background Sync events for 3 days, even when DevTools is not open: Open DevTools. Open the Application panel. Open the Background Sync pane. Figure 5. The Background Sync pane. Click Record . After triggering some Background Sync activity, DevTools logs the events to the table. Figure 6. A log of events in the Background Sync pane. Click an event to view its details in the space below the table. Figure 7. Viewing the details of an event in the Background Sync pane.

Notifications

After a service worker has received a Push Message from a server, the service worker uses the Notifications API to display the data to a user. To log Notifications for 3 days, even when DevTools is not open: Open DevTools. Open the Application panel. Open the Notifications pane. Figure 8. The Notifications pane. Click Record . After triggering some Notifications activity, DevTools logs the events to the table. Figure 9. A log of events in the Notifications pane. Click an event to view its details in the space below the table. Figure 10. Viewing the details of an event in the Notifications pane.

Push Messages

To display a push notification to a user, a service worker must first use the Push Message API to receive data from a server. When the service worker is ready to display the notification, it uses the Notifications API. To log Push Messages for 3 days, even when DevTools is not open: Open DevTools. Open the Application panel. Open the Push Messaging pane. Figure 11. The Push Messaging pane. Click Record . After triggering some Push Message activity, DevTools logs the events to the table. Figure 12. A log of events in the Push Messaging pane. Click an event to view its details in the space below the table. Figure 13. Viewing the details of an event in the Push Messaging pane. Improve article


Ignore Chrome Extension Scripts

When using the Sources panel of Chrome DevTools to step through code, sometimes you pause on code that you don't recognize. You're probably paused on the code of one of the Chrome Extensions that you've installed. To never pause on extension code: Press F1 to open Settings. Or click Settings . Open the Ignore List tab. Enable the Add content scripts to ignore list checkbox. Figure 1. Enabling the ignore list checkbox Improve article


Disable JavaScript

To see how a web page looks and behaves when JavaScript is disabled: Open Chrome DevTools. Press Control+Shift+P or Command+Shift+P (Mac) to open the Command Menu. Figure 1. The Command Menu Start typing javascript, select Disable JavaScript, and then press Enter to run the command. JavaScript is now disabled. Figure 2. Selecting Disable JavaScript in the Command Menu The yellow warning icon next to Sources reminds you that JavaScript is disabled. Figure 3. The warning icon next to Sources JavaScript will remain disabled in this tab so long as you have DevTools open. You may want to reload the page to see if and how the page depends on JavaScript while loading. To re-enable JavaScript: Open the Command Menu again and run the Enable JavaScript command. Close DevTools. Improve article


Analyze runtime performance

Note: See Optimize Website Speed to learn how make your pages load faster. Runtime performance is how your page performs when it is running, as opposed to loading. This tutorial teaches you how to use the Chrome DevTools Performance panel to analyze runtime performance. In terms of the RAIL model, the skills you learn in this tutorial are useful for analyzing the Response, Animation, and Idle phases of your page. Caution Caution: This tutorial is based on Chrome 59. If you use another version of Chrome, the UI and features of DevTools may be different. Check chrome://help to see what version of Chrome you're running.

Get started

In this tutorial, you open DevTools on a live page and use the Performance panel to find a performance bottleneck on the page. Open Google Chrome in Incognito Mode. Incognito Mode ensures that Chrome runs in a clean state. For example, if you have a lot of extensions installed, those extensions might create noise in your performance measurements. Load the following page in your Incognito window. This is the demo that you're going to profile. The page shows a bunch of little blue squares moving up and down. https://googlechrome.github.io/devtools-samples/jank/ Press Command+Option+I (Mac) or Control+Shift+I (Windows, Linux) to open DevTools. Figure 1. The demo on the left, and DevTools on the right Note: For the rest of the screenshots, DevTools is undocked to a separate window so that you can see its contents better.

 Simulate a mobile CPU

Mobile devices have much less CPU power than desktops and laptops. Whenever you profile a page, use CPU Throttling to simulate how your page performs on mobile devices. In DevTools, click the Performance tab. Make sure that the Screenshots checkbox is enabled. Click Capture Settings . DevTools reveals settings related to how it captures performance metrics. For CPU, select 2x slowdown. DevTools throttles your CPU so that it's 2 times slower than usual. Figure 2. CPU throttling, outlined in blue Note: When testing other pages, if you want to ensure that they work well on low-end mobile devices, set CPU Throttling to 20x slowdown. This demo doesn't work well with 20x slowdown, so it just uses 2x slowdown for instructional purposes.

 Set up the demo

It's hard to create a runtime performance demo that works consistently for all readers of this website. This section lets you customize the demo to ensure that your experience is relatively consistent with the screenshots and descriptions you see in this tutorial, regardless of your particular setup. Keep clicking Add 10 until the blue squares move noticeably slower than before. On a high-end machine, it may take about 20 clicks. Click Optimize. The blue squares should move faster and more smoothly. Note: If you don't see a noticeable difference between the optimized and un-optimized versions, try clicking Subtract 10 a few times and trying again. If you add too many blue squares, you're just going to max out the CPU and you're not going to see a major difference in the results for the two versions. Click Un-Optimize. The blue squares move slower and with more jank again.

 Record runtime performance

When you ran the optimized version of the page, the blue squares move faster. Why is that? Both versions are supposed to move each square the same amount of space in the same amount of time. Take a recording in the Performance panel to learn how to detect the performance bottleneck in the un-optimized version. In DevTools, click Record . DevTools captures performance metrics as the page runs. Figure 3: Profiling the page Wait a few seconds. Click Stop. DevTools stops recording, processes the data, then displays the results on the Performance panel. Figure 4: The results of the profile Wow, that's an overwhelming amount of data. Don't worry, it'll all make more sense shortly.

Analyze the results

Once you've got a recording of the page's performance, you can measure how poor the page's performance is, and find the cause(s).

 Analyze frames per second

The main metric for measuring the performance of any animation is frames per second (FPS). Users are happy when animations run at 60 FPS. Look at the FPS chart. Whenever you see a red bar above FPS, it means that the framerate dropped so low that it's probably harming the user experience. In general, the higher the green bar, the higher the FPS. Figure 5: The FPS chart, outlined in blue Below the FPS chart you see the CPU chart. The colors in the CPU chart correspond to the colors in the Summary tab, at the bottom of the Performance panel. The fact that the CPU chart is full of color means that the CPU was maxed out during the recording. Whenever you see the CPU maxed out for long periods, it's a cue to find ways to do less work. Figure 6: The CPU chart and Summary tab, outlined in blue Hover your mouse over the FPS, CPU, or NET charts. DevTools shows a screenshot of the page at that point in time. Move your mouse left and right to replay the recording. This is called scrubbing, and it's useful for manually analyzing the progression of animations. Figure 7: Viewing a screenshot of the page around the 2000ms mark of the recording In the Frames section, hover your mouse over one of the green squares. DevTools shows you the FPS for that particular frame. Each frame is probably well below the target of 60 FPS. Figure 8: Hovering over a frame Of course, with this demo, it's pretty obvious that the page is not performing well. But in real scenarios, it may not be so clear, so having all of these tools to make measurements comes in handy.

Bonus: Open the FPS meter

Another handy tool is the FPS meter, which provides real-time estimates for FPS as the page runs. Press Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux) to open the Command Menu. Start typing Rendering in the Command Menu and select Show Rendering. In the Rendering tab, enable FPS Meter. A new overlay appears in the top-right of your viewport. Figure 9: The FPS meter Disable the FPS Meter and press Escape to close the Rendering tab. You won't be using it in this tutorial.

 Find the bottleneck

Now that you've measured and verified that the animation is not performing well, the next question to answer is: why? Note the summary tab. When no events are selected, this tab shows you a breakdown of activity. The page spent most of its time rendering. Since performance is the art of doing less work, your goal is to reduce the amount of time spent doing rendering work. Figure 10: The Summary tab, outlined in blue Expand the Main section. DevTools shows you a flame chart of activity on the main thread, over time. The x-axis represents the recording, over time. Each bar represents an event. A wider bar means that event took longer. The y-axis represents the call stack. When you see events stacked on top of each other, it means the upper events caused the lower events. Figure 11: The Main section, outlined in blue There's a lot of data in the recording. Zoom in on a single Animation Frame Fired event by clicking, holding, and dragging your mouse over the Overview, which is the section that includes the FPS, CPU, and NET charts. The Main section and Summary tab only display information for the selected portion of the recording. Figure 12: Zoomed in on a single Animation Frame Fired event Note: Another way to zoom is to focus the Main section by clicking its background or selecting an event, and then press the W, A, S, and D keys. Note the red triangle in the top-right of the Animation Frame Fired event. Whenever you see a red triangle, it's a warning that there may be an issue related to this event. Note: The Animation Frame Fired event occurs whenever a requestAnimationFrame() callback is executed. Click the Animation Frame Fired event. The Summary tab now shows you information about that event. Note the reveal link. Clicking that causes DevTools to highlight the event that initiated the Animation Frame Fired event. Also note the app.js:94 link. Clicking that jumps you to the relevant line in the source code. Figure 13: More information about the Animation Frame Fired event Note: After selecting an event, use the arrow keys to select the events next to it. Under the app.update event, there's a bunch of purple events. If they were wider, it looks as though each one might have a red triangle on it. Click one of the purple Layout events now. DevTools provides more information about the event in the Summary tab. Indeed, there's a warning about forced reflows (another word for layout). In the Summary tab, click the app.js:70 link under Layout Forced. DevTools takes you to the line of code that forced the layout. Figure 13: The line of code that caused the forced layout Note: The problem with this code is that, in each animation frame, it changes the style for each square, and then queries the position of each square on the page. Because the styles changed, the browser doesn't know if each square's position changed, so it has to re-layout the square in order to compute its position. See Avoid forced synchronous layouts to learn more. Phew! That was a lot to take in, but you now have a solid foundation in the basic workflow for analyzing runtime performance. Good job.

 Bonus: Analyze the optimized version

Using the workflows and tools that you just learned, click Optimize on the demo to enable the optimized code, take another performance recording, and then analyze the results. From the improved framerate to the reduction in events in the Main section's flame chart, you can see that the optimized version of the app does much less work, resulting in better performance. Note: Even this "optimized" version isn't that great, because it still manipulates the top property of each square. A better approach is to stick to properties that only affect compositing. See Use transform and opacity changes for animations for more information.

Next steps

The foundation for understanding performance is the RAIL model. This model teaches you the performance metrics that are most important to your users. See Measure Performance With The RAIL Model to learn more. To get more comfortable with the Performance panel, practice makes perfect. Try profiling your own pages and analyzing the results. If you have any questions about your results, open a Stack Overflow question tagged with google-chrome-devtools. Include screenshots or links to reproducible pages, if possible. To become an expert in runtime performance, you've got to learn how the browser translates HTML, CSS, and JS into pixels on a screen. The best place to start is the Rendering Performance Overview. The Anatomy Of A Frame dives into even more detail. Last, there are many ways to improve runtime performance. This tutorial focused on one particular animation bottleneck to give you a focused tour through the Performance panel, but it's only one of many bottlenecks you may encounter. The rest of the Rendering Performance series has a lot of good tips for improving various aspects of runtime performance, such as: Optimizing JS Execution Reduce The Scope And Complexity Of Style Calculations Avoid Large, Complex Layouts And Layout Thrashing Simplify Paint Complexity And Reduce Paint Areas Stick To Compositor-Only Properties And Manage Layer Count Debounce Your Input Handlers Improve article


Optimize website speed

Goal of tutorial

This tutorial teaches you how to use Chrome DevTools to find ways to make your websites load faster. Read on, or watch the video version of this tutorial:

Prerequisites

You should have basic web development experience, similar to what's taught in this Introduction to Web Development class. You don't need to know anything about load performance. You'll learn about it in this tutorial!

Introduction

This is Tony. Tony is very famous in cat society. He has built a website so that his fans can learn what his favorite foods are. His fans love the site, but Tony keeps hearing complaints that the site loads slowly. Tony has asked you to help him speed the site up. Figure 1. Tony the cat

Step 1: Audit the site

Whenever you set out to improve a site's load performance, always start with an audit. The audit has 2 important functions: It creates a baseline for you to measure subsequent changes against. It gives you actionable tips on what changes will have the most impact.

 Set up

But first, you need to set up the site so that you can make changes to it later: Go to chrome://version to check what version of Chrome you're using. This tutorial was made with Chrome 68. If you're using an earlier or later version, some features may look different or not be available. You should be able to complete the tutorial still, just keep in mind that your UI may look different than the screenshots. Open the source code for the site. This tab will be referred to as the editor tab. Figure 2. The editor tab Click tony. A menu appears. Figure 3. The menu that appears after clicking tony Click Remix This. The name of the project changes from tony to some randomly-generated name. You now have your own editable copy of the code. Later on, you'll make changes to this code. Click Show Live. The demo opens in a new tab. This tab will be referred to as the demo tab. It may take a while for the site to load. Figure 4. The demo tab Press Command+Option+J (Mac) Control+Shift+J (Windows, Linux, Chrome OS). Chrome DevTools opens up alongside the demo. Figure 5. DevTools and the demo For the rest of the screenshots in this tutorial, DevTools will be shown as a separate window. You can do this by pressing Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux, Chrome OS) to open the Command Menu, typing Undock, and then selecting Undock into separate window. Figure 6. Undocked DevTools

 Establish a baseline

The baseline is a record of how the site performed before you made any performance improvements. Click the Audits tab. It may be hidden behind the More Panels Lighthouse. Figure 7. The Audits panel Match your audit configuration settings to those in Figure 7. Here's an explanation of the different options: Device. Setting to Mobile changes the user agent string and simulates a mobile viewport. Setting to Desktop pretty much just disables the Mobile changes. Audits. Disabling a category prevents the Audits panel from running those audits, and excludes those audits from your report. You can leave the other categories enabled, if you want to see the types of recommendations they provide. Disabling categories slightly speeds up the auditing process. Throttling. Setting to Simulated Fast 3G, 4x CPU Slowdown simulates the typical conditions of browsing on a mobile device. It's called "simulated" because the Audits panel doesn't actually throttle during the auditing process. Instead, it just extrapolates how long the page would take to load under mobile conditions. The Applied... setting, on the other hand, actually throttles your CPU and network, with the tradeoff of a longer auditing process. Clear Storage. Enabling this checkbox clears all storage associated with the page before every audit. Leave this setting on if you want to audit how first-time visitors experience your site. Disable this setting when you want the repeat-visit experience. Click Run Audits. After 10 to 30 seconds, the Audits panel shows you a report of the site's performance. Figure 8. The Audits panel's report of the site's performance

Handling report errors

If you ever get an error in your Audits panel report, try running the demo tab from an incognito window with no other tabs open. This ensures that you're running Chrome from a clean state. Chrome Extensions in particular often interfere with the auditing process. Figure 9. A report that errored

 Understand your report

The number at the top of your report is the overall performance score for the site. Later, as you make changes to the code, you should see this number rise. A higher score means better performance. Figure 10. The overall performance score The Metrics section provides quantitative measurements of the site's performance. Each metric provides insight into a different aspect of the performance. For example, First Contentful Paint tells you when content is first painted to the screen, which is an important milestone in the user's perception of the page load, whereas Time To Interactive marks the point at which the page appears ready enough to handle user interactions. Figure 11. The Metrics section Hover over a metric to see a description of it, and click Learn More to read documentation about it. Figure 12. Hovering over the First Meaningful Paint metric Below Metrics is a collection of screenshots that show you how the page looked as it loaded. Figure 13. Screenshots of how the page looked while loading The Opportunities section provides specific tips on how to improve this particular page's load performance. Figure 14. The Opportunities section Click an opportunity to learn more about it. Figure 15. More information about the text compression opportunity Click Learn More to see documentation about why an opportunity is important, and specific recommendations on how to fix it. Figure 16. Documentation for the text compression opportunity The Diagnostics section provides more information about factors that contribute to the page's load time. Figure 17. The Diagnostics section The Passed Audits section shows you what the site is doing correctly. Click to expand the section. Figure 18. The Passed Audits section

Step 2: Experiment

The Opportunities section of your audit report gives you tips on how to improve the page's performance. In this section, you implement the recommended changes to the codebase, auditing the site after each change to measure how it affects site speed.

 Enable text compression

Your report says that enabling text compression is one of the top opportunities for improving the page's performance. Text compression is when you reduce, or compress, the size of a text file before sending it over the network. Kind of like how you might zip a folder before emailing it to reduce its size. Before you enable compression, here are a couple of ways you can manually check whether text resources are compressed. Click the Network tab. Figure 19. The Network panel Click Use Large Request Rows . The height of the rows in the table of network requests increases. Figure 20. Large rows in the network requests table If you don't see the Size column in the table of network requests, click the table header and then select Size. Each Size cell shows two values. The top value is the size of the downloaded resource. The bottom value is the size of the uncompressed resource. If the two values are the same, then the resource is not being compressed when it's sent over the network. For example, in Figure 20 the top and bottom values for bundle.js are both 1.4 MB. You can also check for compression by inspecting a resource's HTTP headers: Click bundle.js. Click the Headers tab. Figure 21. The Headers tab Search the Response Headers section for a content-encoding header. You shouldn't see one, meaning that bundle.js was not compressed. When a resource is compressed, this header is usually set to gzip, deflate, or br. See Directives for an explanation of these values. Enough with the explanations. Time to make some changes! Enable text compression by adding a couple of lines of code: In the editor tab, click server.js. Figure 22. Editing server.js Add the following code to server.js. Make sure to put app.use(compression()) before app.use(express.static('build')). ... const fs = require('fs'); const compression = require('compression'); app.use(compression()); app.use(express.static('build')); ... Note: Usually, you'd have to install the compression package via something like npm i -S compression, but this has already been done for you. Wait for Glitch to deploy the new build of the site. The fancy animation that you see next to Logs and Show means that the site is getting rebuilt and redeployed. The change is ready when you see Show Live again. Figure 23. The animation that indicates that the site is getting built Use the workflows that you learned earlier to manually check that the compression is working: Go back to the demo tab and reload the page. The Size column should now show 2 different values for text resources like bundle.js. In Figure 24 the top value of 261 KB for bundle.js is the size of the file that was sent over the network, and the bottom value of 1.4 MB is the uncompressed file size. Figure 24. The Size column now shows 2 different values for text resources The Response Headers section for bundle.js should now include a content-encoding: gzip header. Figure 25. The Response Headers section now contains a content-encoding header Audit the page again to measure what kind of impact text compression has on the page's load performance: Click the Audits tab. Click Perform an audit . Leave the settings the same as before. Click Run audit. Figure 26. An Audits report after enabling text compression Woohoo! That looks like progress. Your overall performance score should have increased, meaning that the site is getting faster.

Text compression in the real world

Most servers really do have simple fixes like this for enabling compression! Just do a search on how to configure whatever server you use to compress text.

 Resize images

Your new report says that properly sizing images is another big opportunity. Resizing images helps speed up load time by reducing the file size of images. If your user is viewing your images on a mobile device screen that's 500-pixels-wide, there's really no point in sending a 1500-pixel-wide image. Ideally, you'd send a 500-pixel-wided image, at most. In your report, click Properly size images to see what images should be resized. It looks like all 4 images are bigger than necessary. Figure 27. Details about the Properly size images opportunity Back in the editor tab, open src/model.js. Replace const dir = 'big' with const dir = 'small'. This directory contains copies of the same images which have been resized. Audit the page again to see how this change affects load performance. Figure 28. An Audits report after resizing images Looks like the change only has a minor affect on the overall performance score. However, one thing that the score doesn't show clearly is how much network data you're saving your users. The total size of the old photos was around 5.3 megabytes, whereas now it's only about 0.18 megabytes.

Resizing images in the real world

For a small app, doing a one-off resize like this may be good enough. But for a large app, this obviously isn't scalable. Here are some strategies for managing images in large apps: Resize images during your build process. Create multiple sizes of each image during the build process and then use srcset in your code. At runtime, the browser takes care of choosing what size is best for the device it's running on. See Relative-sized images. Use an image CDN that lets you dynamically resize an image when you request it. At the very least, optimize each image. This can often create huge savings. Optimization is when you run an image through a special program that reduces the size of the image file. See Essential Image Optimization for more tips.

 Eliminate render-blocking resources

Your latest report says that eliminating render-blocking resources is now the biggest opportunity. A render-blocking resource is an external JavaScript or CSS file that the browser must download, parse, and execute before it can show the page. The goal is to only run the core CSS and JavaScript code that is required to display the page properly. The first task, then, is to find code that doesn't need to be executed on page load. Click Eliminate render-blocking resources to see the resources that are blocking: lodash.js and jquery.js. Figure 29. More information about the Reduce render-blocking resources opportunity Press Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux, Chrome OS) to open the Command Menu, start typing Coverage, and then select Show Coverage. Figure 30. Opening the Command Menu from the Audits panel Figure 31. The Coverage tab Click Reload . The Coverage tab provides an overview of how much of the code in bundle.js, jquery.js, and lodash.js is being executed while the page loads. Figure 32 says that about 76% and 30% of the jQuery and Lodash files aren't used, respectively. Figure 32. The Coverage report Click the jquery.js row. DevTools opens the file in the Sources panel. A line of code was executed if it has a green bar next to it. A red bar means it was not executed, and is definitely not needed on page load. Figure 33. Viewing the jQuery file in the Sources panel Scroll through the jQuery code a bit. Some of the lines that get "executed" are actually just comments. Running this code through a minifier that strips comments is another way to reduce the size of this file. In short, when you're working with your own code, the Coverage tab can help you analyze your code, line-by-line, and only ship the code that's needed for page load. Are the jquery.js and lodash.js files even needed to load the page? The Request Blocking tab can show you what happens when resources aren't available. Click the Network tab. Press Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux, Chrome OS) to open the Command Menu again. Start typing blocking and then select Show Request Blocking. Figure 34. The Request Blocking tab Click Add Pattern , type /libs/*, and then press Enter to confirm. Figure 35. Adding a pattern to block any request to the libs directory Reload the page. The jQuery and Lodash requests are red, meaning that they were blocked. The page still loads and is interactive, so it looks like these resources aren't needed whatsoever! Figure 36. The Network panel shows that the requests have been blocked Click Remove all patterns to delete the /libs/* blocking pattern. In general, the Request Blocking tab is useful for simulating how your page behaves when any given resource isn't available. Now, remove the references to these files from the code and audit the page again: Back in the editor tab, open template.html. Delete <script src="/libs/lodash.js"> and <script src="/libs/jquery.js"></script>. Wait for the site to re-build and re-deploy. Audit the page again from the Audits panel. Your overall score should have improved again. Figure 37. An Audits report after removing the render-blocking resources

Optimizing the Critical Rendering Path in the real-world

The Critical Rendering Path refers to the code that you need to load a page. In general, you can speed up page load by only shipping critical code during the page load, and then lazy-loading everything else. It's unlikely that you'll find scripts that you can remove outright, but you will often find that many scripts don't need to be requested during the page load, and can instead be requested asynchronously. See Using async or defer. If you're using a framework, check if it has a production mode. This mode may use a feature such as tree shaking in order to eliminate unnecessary code that is blocking the critical render.

 Do less main thread work

Your latest report shows some minor potential savings in the Opportunities section, but if you look down in the Diagnostics section, it looks like the biggest bottleneck is too much main thread activity. The main thread is where the browser does most of the work needed to display a page, such as parsing and executing HTML, CSS, and JavaScript. The goal is to use the Performance panel to analyze what work the main thread is doing while the page loads, and find ways to defer or remove unnecessary work. Click the Performance tab. Click Capture Settings . Set Network to Slow 3G and CPU to 6x slowdown. Mobile devices typically have more hardware constraints than laptops or desktops, so these settings let you experience the page load as if you were using a less powerful device. Click Reload . DevTools reloads the page and then produces a visualization of all it had to do in order to load the page. This visualization will be referred to as the trace. Figure 38. The Performance panel's trace of the page load The trace shows activity chronologically, from left to right. The FPS, CPU, and NET charts at the top give you an overview of frames per second, CPU activity, and network activity. The wall of yellow that you see in Figure 39 means that the CPU was completely busy with scripting activity. This is a clue that you may be able to speed up page load by doing less JavaScript work. Figure 39. The Overview section of the trace Investigate the trace to find ways to do less JavaScript work: Click the User Timing section to expand it. Based on the fact that there seems to be a bunch of User Timing measures from React, it seems like Tony's app is using the development mode of React. Switching to the production mode of React will probably yield some easy performance wins. Figure 40. The User Timing section Click User Timing again to collapse that section. Browse the Main section. This section shows a chronological log of main thread activity, from left to right. The y-axis (top to bottom) shows why events occurred. For example, in Figure 41, the Evaluate Script event caused the (anonymous) function to execute, which caused ../rbd/pnpm-volume/... to execute, which caused __webpack__require__ to execute, and so on. Figure 41. The Main section Scroll down to the bottom of the Main section. When you use a framework, most of the upper activity is caused by the framework, which is usually out of your control. The activity caused by your app is usually at the bottom. In this app, it seems like a function called App is causing a lot of calls to a mineBitcoin function. It sounds like Tony might be using the devices of his fans to mine cryptocurrency... Figure 42. Hovering over the mineBitcoin activity Note: Although the calls that your framework makes are usually out of your control, sometimes you may structure your app in a way that causes the framework to run inefficiently. Restructuring your app to use the framework efficiently can be a way to do less main thread work. However, this requires a deep understanding of how your framework works, and what kind of changes you can make in your own code in order to use the framework more efficiently. Expand the Bottom-Up section. This tab breaks down what activities took up the most time. If you don't see anything in the Bottom-Up section, click the label for Main section. The Bottom-Up section only shows information for whatever activity, or group of activity, you have currently selected. For example, if you clicked on one of the mineBitcoin activities, the Bottom-Up section is only going to show information for that one activity. Figure 43. The Bottom-Up tab The Self Time column shows you how much time was spent directly in each activity. For example, Figure 43 shows that about 57% of main thread time was spent on the mineBitcoin function. Time to see whether using production mode and reducing JavaScript activity will speed up the page load. Start with production mode: In the editor tab, open webpack.config.js. Change "mode":"development" to "mode":"production". Wait for the new build to deploy. Audit the page again. Figure 44. An Audits report after configuring webpack to use production mode Reduce JavaScript activity by removing the call to mineBitcoin: In the editor tab, open src/App.jsx. Comment out the call to this.mineBitcoin(1500) in the constructor. Wait for the new build to deploy. Audit the page again. Figure 45. An Audits report after removing unnecessary JavaScript work Looks like that last change caused a massive jump in performance! Note: This section provided a rather brief introduction to the Performance panel. See Performance Analysis Reference to learn more about how you can use it to analyze page performance.

Doing less main thread work in the real world

In general, the Performance panel is the most common way to understand what activity your site does as it loads, and find ways to remove unnecessary activity. If you'd prefer an approach that feels more like console.log(), the User Timing API lets you arbitrarily mark up certain phases of your app lifecycle, in order to track how long each of those phases takes.

A special thank you from Tony

Tony's fans love how fast the site feels now, and Tony is very thankful for your help. Click Receive Gift below to receive a special gift from Tony.

Summary

Whenever you set out to optimize a site's load performance, always start with an audit. The audit establishes a baseline, and gives you tips on how to improve. Make one change at a time, and audit the page after each change in order to see how that isolated change affects performance.

Next steps

Run audits on your own site! If you need help interpreting your report, or finding ways to improve your load performance, check out Feedback for ways to get help from the DevTools community. Stack Overflow, the mailing list, or Twitter are probably best for these types of questions. Please leave feedback on this tutorial. I really do use the data to make better tutorials for you. File bugs on this doc in the Web Fundamentals repository. File bug reports on DevTools at Chromium Bugs. Discuss features and changes on the Mailing List. Please don't use the mailing list for support questions. Use Stack Overflow, instead. Get general help on how to use DevTools on Stack Overflow. Please don't file bugs on Stack Overflow. Use Chromium Bugs, instead. Tweet us at @ChromeDevTools. Improve article


Performance features reference

This page is a comprehensive reference of Chrome DevTools features related to analyzing performance. See Get Started With Analyzing Runtime Performance for a guided tutorial on how to analyze a page's performance using Chrome DevTools.

Record performance

 Record runtime performance

Record runtime performance when you want to analyze the performance of a page as it's running, as opposed to loading. Go to the page that you want to analyze. Click the Performance tab in DevTools. Click Record . Figure 1. Record, outlined in blue Interact with the page. DevTools records all page activity that occurs as a result of your interactions. Click Record again or click Stop to stop recording.

 Record load performance

Record load performance when you want to analyze the performance of a page as it's loading, as opposed to running. Go to the page that you want to analyze. Open the Performance panel of DevTools. Click Reload page . DevTools records performance metrics while the page reloads and then automatically stops the recording a couple seconds after the load finishes. Figure 2. Reload page, outlined in blue DevTools automatically zooms in on the portion of the recording where most of the activity occurred. Figure 3. A page-load recording

 Capture screenshots while recording

Enable the Screenshots checkbox to capture a screenshot of every frame while recording. Figure 4. The Screenshots checkbox See View a screenshot to learn how to interact with screenshots.

 Force garbage collection while recording

While you are recording a page, click Collect garbage to force garbage collection. Figure 5. Collect garbage, outlined in blue

 Show recording settings

Click Capture settings to expose more settings related to how DevTools captures performance recordings. Figure 6. The Capture settings section, outlined in blue

 Disable JavaScript samples

By default, the Main section of a recording displays detailed call stacks of JavaScript functions that were called during the recording. To disable these call stacks: Open the Capture settings menu. See Show recording settings. Enable the Disable JavaScript Samples checkbox. Take a recording of the page. Figure 7 and Figure 8 show the difference between disabling and enabling JavaScript samples. The Main section of the recording is much shorter when sampling is disabled, because it omits all of the JavaScript call stacks. Figure 7. An example of a recording when JS samples are disabled Figure 8. An example of a recording when JS samples are enabled

 Throttle the network while recording

To throttle the network while recording: Open the Capture settings menu. See Show recording settings. Set Network to the desired level of throttling.

 Throttle the CPU while recording

To throttle the CPU while recording: Open the Capture settings menu. See Show recording settings. Set CPU to the desired level of throttling. Throttling is relative to your computer's capabilities. For example, the 2x slowdown option makes your CPU operate 2 times slower than its usual ability. DevTools can't truly simulate the CPUs of mobile devices, because the architecture of mobile devices is very different from that of desktops and laptops.

 Enable advanced paint instrumentation

To view detailed paint instrumentation: Open the Capture settings menu. See Show recording settings. Check the Enable advanced paint instrumentation checkbox. To learn how to interact with the paint information, see View layers and View paint profiler.

Save a recording

To save a recording, right-click and select Save Profile. Figure 9. Save Profile

Load a recording

To load a recording, right-click and select Load Profile. Figure 10. Load Profile

Clear the previous recording

After making a recording, press Clear recording to clear that recording from the Performance panel. Figure 11. Clear recording, outlined in blue

Analyze a performance recording

After you record runtime performance or record load performance, the Performance panel provides a lot of data for analyzing the performance of what just happened.

 Select a portion of a recording

Drag your mouse left or right across the Overview to select a portion of a recording. The Overview is the section that contains the FPS, CPU, and NET charts. Figure 12. Dragging the mouse across the Overview to zoom To select a portion using the keyboard: Click on the background of the Main section, or any of the sections next to it, such as Interactions, Network, or GPU. This keyboard workflow only works when one of these sections is in focus. Use the W, A, S, D keys to zoom in, move left, zoom out, and move right, respectively. To select a portion using a trackpad: Hover your mouse over the Overview section or the Details section. The Overview section is the area containing the FPS, CPU, and NET charts. The Details section is the area containing the Main section, the Interactions section, and so on. Using two fingers, swipe up to zoom out, swipe left to move left, swipe down to zoom in, and swipe right to move right. To scroll a long flame chart in the Main section or any of its neighbors, click and hold while dragging up and down. Drag left and right to move what portion of the recording is selected.

 Search activities

Press Command+F (Mac) or Control+F (Windows, Linux) to open the search box at the bottom of the Performance panel. Figure 13. Using regex in the search box at the bottom of the window to find any activity that begins with E To navigate activities that match your query: Use the Previous buttons. Press Shift+Enter to select the previous or Enter to select the next. To modify query settings: Press Case sensitive to make the query case sensitive. Press Regex to use a regular expression in your query. To hide the search box, press Cancel.

 View main thread activity

Use the Main section to view activity that occurred on the page's main thread. Figure 14. The Main section, outlined in blue Click on an event to view more information about it in the Summary tab. DevTools outlines the selected event in blue. Figure 15. More information about the Me function call event in the Summary tab DevTools represents main thread activity with a flame chart. The x-axis represents the recording over time. The y-axis represents the call stack. The events on top cause the events below it. Figure 16. A flame chart in the Main section In Figure 16, a click event caused a function call in script_foot_closure.js on line 53. Below Function Call you see that an anonymous function was called. That anonymous function then called Me(), which then called Se(), and so on. DevTools assigns scripts random colors. In Figure 16, function calls from one script are colored light green. Calls from another script are colored beige. The darker yellow represents scripting activity, and the purple event represents rendering activity. These darker yellow and purple events are consistent across all recordings. See Disable JavaScript samples if you want to hide the detailed flame chart of JavaScript calls. When JS samples are disabled, you only see high-level events such as Event (click) and Function Call (script_foot_closure.js:53) from Figure 16.

 View activities in a table

After recording a page, you don't need to rely solely on the Main section to analyze activities. DevTools also provides three tabular views for analyzing activities. Each view gives you a different perspective on the activities: When you want to view the root activities that cause the most work, use the Call Tree tab. When you want to view the activities where the most time was directly spent, use the Bottom-Up tab. When you want to view the activities in the order in which they occurred during the recording, use the Event Log tab. Note: The next three sections all refer to the same demo. You can run the demo yourself at Activity Tabs Demo and see the source at GoogleChrome/devtools-samples/perf/activitytabs.html.

Root activities

Here's an explanation of the root activities concept that's mentioned in the Call Tree tab, Bottom-Up tab, and Event Log sections. Root activities are those which cause the browser to do some work. For example, when you click a page, the browser fires an Event activity as the root activity. That Event might cause a handler to execute, and so on. In the Main section's flame chart, root activities are at the top of the chart. In the Call Tree and Event Log tabs, root activities are the top-level items. See The Call Tree tab for an example of root activities.

The Call Tree tab

Use the Call Tree tab to view which root activities cause the most work. The Call Tree tab only displays activities during the selected portion of the recording. See Select a portion of a recording to learn how to select portions. Figure 17. The Call Tree tab In Figure 17, the top-level of items in the Activity column, such as Event, Paint, and Composite Layers are root activities. The nesting represents the call stack. For example, in Figure 17, Event caused Function Call, which caused button.addEventListener, which caused b, and so on. Self Time represents the time directly spent in that activity. Total Time represents the time spent in that activity or any of its children. Click Self Time, Total Time, or Activity to sort the table by that column. Use the Filter text box to filter events by activity name. By default the Grouping menu is set to No Grouping. Use the Grouping menu to sort the activity table based on various criteria. Click Show Heaviest Stack to reveal another table to the right of the Activity table. Click on an activity to populate the Heaviest Stack table. The Heaviest Stack table shows you which children of the selected activity took the longest time to execute.

The Bottom-Up tab

Use the Bottom-Up tab to view which activities directly took up the most time in aggregate. The Bottom-Up tab only displays activities during the selected portion of the recording. See Select a portion of a recording to learn how to select portions. Figure 18. The Bottom-Up tab In the Main section flame chart of Figure 18, you can see that almost practically all of the time was spent executing the three calls to wait(). Accordingly, the top activity in the Bottom-Up tab of Figure 18 is wait. In the flame chart of Figure 18, the yellow below the calls to wait are actually thousands of Minor GC calls. Accordingly, you can see that in the Bottom-Up tab, the next most expensive activity is Minor GC. The Self Time column represents the aggregated time spent directly in that activity, across all of its occurrences. The Total Time column represents aggregated time spent in that activity or any of its children.

The Event Log tab

Use the Event Log tab to view activities in the order in which they occurred during the recording. The Event Log tab only displays activities during the selected portion of the recording. See Select a portion of a recording to learn how to select portions. Figure 19. The Event Log tab The Start Time column represents the point at which that activity started, relative to the start of the recording. For example, the start time of 1573.0 ms for the selected item in Figure 19 means that activity started 1573 ms after the recording started. The Self Time column represents the time spent directly in that activity. The Total Time columns represents time spent directly in that activity or in any of its children. Click Start Time, Self Time, or Total Time to sort the table by that column. Use the Filter text box to filter activities by name. Use the Duration menu to filter out any activities that took less than 1 ms or 15 ms. By default the Duration menu is set to All, meaning all activities are shown. Disable the Loading, Scripting, Rendering, or Painting checkboxes to filter out all activities from those categories.

 View GPU activity

View GPU activity in the GPU section. Figure 20. The GPU section, outlined in blue

 View raster activity

View raster activity in the Raster section. Figure 21. The Raster section, outlined in blue

 View interactions

Use the Interactions section to find and analyze user interactions that happened during the recording. Figure 22. The Interactions section, outlined in blue A red line at the bottom of an interaction represents time spent waiting for the main thread. Click an interaction to view more information about it in the Summary tab.

 Analyze frames per second (FPS)

DevTools provides numerous ways to analyze frames per second: Use the FPS chart to get an overview of FPS over the duration of the recording. Use the Frames section to view how long a particular frame took. Use the FPS meter for a realtime estimate of FPS as the page runs. See View frames per second in realtime with the FPS meter.

The FPS chart

The FPS chart provides an overview of the frame rate across the duration of a recording. In general, the higher the green bar, the better the frame rate. A red bar above the FPS chart is a warning that the frame rate dropped so low that it probably harmed the user's experience. Figure 20. The FPS chart, outlined in blue

The Frames section

The Frames section tells you exactly how long a particular frame took. Hover over a frame to view a tooltip with more information about it. Figure 21. Hovering over a frame Click on a frame to view even more information about the frame in the Summary tab. DevTools outlines the selected frame in blue. Figure 22. Viewing a frame in the Summary tab

 View network requests

Expand the Network section to view a waterfall of network requests that occurred during the recording. Figure 23. The Network section, outlined in blue Requests are color-coded as follows: HTML: Blue CSS: Purple JS: Yellow Images: Green Click on a request to view more information about it in the Summary tab. For example, in Figure 23 the Summary tab is displaying more information about the blue request that's selected in the Network section. A darker-blue square in the top-left of a request means it's a higher-priority request. A lighter-blue square means lower-priority. For example, in Figure 23 the blue, selected request is higher-priority, and the green one above it is lower-priority. In Figure 24, the request for www.google.com is represented by a line on the left, a bar in the middle with a dark portion and a light portion, and a line on the right. Figure 25 shows the corresponding representation of the same request in the Timing tab of the Network panel. Here's how these two representations map to each other: The left line is everything up to the Connection Start group of events, inclusive. In other words, it's everything before Request Sent, exclusive. The light portion of the bar is Request Sent and Waiting (TTFB). The dark portion of the bar is Content Download. The right line is essentially time spent waiting for the main thread. This is not represented in the Timing tab. Figure 24. The line-bar representation of the www.google.com request Figure 25. The Timing tab representation of the www.google.com request

 View memory metrics

Enable the Memory checkbox to view memory metrics from the last recording. Figure 26. The Memory checkbox, outlined in blue DevTools displays a new Memory chart, above the Summary tab. There's also a new chart below the NET chart, called HEAP. The HEAP chart provides the same information as the JS Heap line in the Memory chart. Figure 27. Memory metrics, above the Summary tab The colored lines on the chart map to the colored checkboxes above the chart. Disable a checkbox to hide that category from the chart. The chart only displays the region of the recording that is currently selected. For example, in Figure 27, the Memory chart is only showing memory usage for the start of the recording, up to around the 1000ms mark.

 View the duration of a portion of a recording

When analyzing a section like Network or Main, sometimes you need a more precise estimate of how long certain events took. Hold Shift, click and hold, and drag left or right to select a portion of the recording. At the bottom of your selection, DevTools shows how long that portion took. Figure 28. The 488.53ms timestamp at the bottom of the selected portion indicates how long that portion took

 View a screenshot

See Capture screenshots while recording to learn how to enable screenshots. Hover over the Overview to view a screenshot of how the page looked during that moment of the recording. The Overview is the section that contains the CPU, FPS, and NET charts. Figure 29. Viewing a screenshot You can also view screenshots by clicking a frame in the Frames section. DevTools displays a small version of the screenshot in the Summary tab. Figure 30. After clicking the 195.5ms frame in the Frames section, the screenshot for that frame is displayed in the Summary tab Click the thumbnail in the Summary tab to zoom in on the screenshot. Figure 31. After clicking the thumbnail in the Summary tab, DevTools zooms in on the screenshot

 View layers information

To view advanced layers information about a frame: Enable advanced paint instrumentation. Select a frame in the Frames section. DevTools displays information about its layers in the new Layers tab, next to the Event Log tab. Figure 32. The Layers tab Hover over a layer to highlight it in the diagram. Figure 33. Highlighting layer #39 To move the diagram: Click Pan Mode to move along the X and Y axes. Click Rotate Mode to rotate along the Z axis. Click Reset Transform to reset the diagram to its original position. See layer analysis in action:

 View paint profiler

To view advanced information about a paint event: Enable advanced paint instrumentation. Select a Paint event in the Main section. Figure 34. The Paint Profiler tab

Analyze rendering performance with the Rendering tab

Use the Rendering tab's features to help visualize your page's rendering performance. To open the Rendering tab: Open the Command Menu. Start typing Rendering and select Show Rendering. DevTools displays the Rendering tab at the bottom of your DevTools window. Figure 35. The Rendering tab

 View frames per second in realtime with the FPS meter

The FPS meter is an overlay that appears in the top-right corner of your viewport. It provides a realtime estimate of FPS as the page runs. To open the FPS meter: Open the Rendering tab. See Analyze rendering performance with the Rendering tab. Enable the FPS Meter checkbox. Figure 36. The FPS meter

 View painting events in realtime with Paint Flashing

Use Paint Flashing to get a realtime view of all paint events on the page. Whenever a part of the page gets re-painted, DevTools outlines that section in green. To enable Paint Flashing: Open the Rendering tab. See Analyze rendering performance with the Rendering tab. Enable the Paint Flashing checkbox. Figure 37. Paint Flashing

 View an overlay of layers with Layer Borders

Use Layer Borders to view an overlay of layer borders and tiles on top of the page. To enable Layer Borders: Open the Rendering tab. See Analyze rendering performance with the Rendering tab. Enable the Layer Borders checkbox. Figure 38. Layer Borders See the comments in debug_colors.cc for an explanation of the color-codings.

 Find scroll performance issues in realtime

Use Scrolling Performance Issues to identify elements of the page that have event listeners related to scrolling that may harm the performance of the page. DevTools outlines the potentially-problematic elements in teal. To view scroll performance issues: Open the Rendering tab. See Analyze rendering performance with the Rendering tab. Enable the Scrolling Performance Issues checkbox. Figure 39. Scrolling Performance Issues is indicating that there's a mousewheel event listener encompassing the entire viewport that may harm scroll performance Improve article


Timeline Event Reference

The timeline events mode displays all events triggered while making a recording. Use the timeline event reference to learn more about each timeline event type.

Common timeline event properties

Certain details are present in events of all types, while some only apply to certain event types. This section lists properties common to different event types. Properties specific to certain event types are listed in the references for those event types that follow.
Property When is it shown
Aggregated time For events with nested events, the time taken by each category of events.
Call Stack For events with child events, the time taken by each category of events.
CPU time How much CPU time the recorded event took.
Details Other details about the event.
Duration (at time-stamp) How long it took the event with all of its children to complete; timestamp is the time at which the event occurred, relative to when the recording started.
Self time How long the event took without any of its children.
Used Heap Size Amount of memory being used by the application when the event was recorded, and the delta (+/-) change in used heap size since the last sampling.

Loading events

This section lists events that belong to Loading category and their properties.
Event Description
Parse HTML Chrome executed its HTML parsing algorithm.
Finish Loading A network request completed.
Receive Data Data for a request was received. There will be one or more Receive Data events.
Receive Response The initial HTTP response from a request.
Send Request A network request has been sent.

 Loading event properties

Property Description
Resource The URL of the requested resource.
Preview Preview of the requested resource (images only).
Request Method HTTP method used for the request (GET or POST, for example).
Status Code HTTP response code.
MIME Type MIME type of the requested resource.
Encoded Data Length Length of requested resource in bytes.

Scripting events

This section lists events that belong to the Scripting category and their properties.
Event Description
Animation Frame Fired A scheduled animation frame fired, and its callback handler invoked.
Cancel Animation Frame A scheduled animation frame was canceled.
GC Event Garbage collection occurred.
DOMContentLoaded The DOMContentLoaded was fired by the browser. This event is fired when all of the page's DOM content has been loaded and parsed.
Evaluate Script A script was evaluated.
Event A JavaScript event ("mousedown", or "key", for example).
Function Call A top-level JavaScript function call was made (only appears when browser enters JavaScript engine).
Install Timer A timer was created with setInterval() or setTimeout().
Request Animation Frame A requestAnimationFrame() call scheduled a new frame
Remove Timer A previously created timer was cleared.
Time A script called console.time()
Time End A script called console.timeEnd()
Timer Fired A timer fired that was scheduled with setInterval() or setTimeout().
XHR Ready State Change The ready state of an XMLHTTPRequest changed.
XHR Load An XMLHTTPRequest finished loading.

 Scripting event properties

Property Description
Timer ID The timer ID.
Timeout The timeout specified by the timer.
Repeats Boolean that specifies if the timer repeats.
Function Call A function that was invoked.

Rendering events

This section lists events that belong to Rendering category and their properties.
Event Description
Invalidate layout The page layout was invalidated by a DOM change.
Layout A page layout was executed.
Recalculate style Chrome recalculated element styles.
Scroll The content of nested view was scrolled.

 Rendering event properties

Property Description
Layout invalidated For Layout records, the stack trace of the code that caused the layout to be invalidated.
Nodes that need layout For Layout records, the number of nodes that were marked as needing layout before the relayout started. These are normally those nodes that were invalidated by developer code, plus a path upward to relayout root.
Layout tree size For Layout records, the total number of nodes under the relayout root (the node that Chrome starts the relayout).
Layout scope Possible values are "Partial" (the re-layout boundary is a portion of the DOM) or "Whole document".
Elements affected For Recalculate style records, the number of elements affected by a style recalculation.
Styles invalidated For Recalculate style records, provides the stack trace of the code that caused the style invalidation.

Painting events

This section lists events that belong to Painting category and their properties.
Event Description
Composite Layers Chrome's rendering engine composited image layers.
Image Decode An image resource was decoded.
Image Resize An image was resized from its native dimensions.
Paint Composited layers were painted to a region of the display. Hovering over a Paint record highlights the region of the display that was updated.

 Painting event properties

Property Description
Location For Paint events, the x and y coordinates of the paint rectangle.
Dimensions For Paint events, the height and width of the painted region.
Improve article


Accessibility features reference

This page is a comprehensive reference of accessibility features in Chrome DevTools. It is intended for web developers who: Have a basic understanding of DevTools, such as how to open it. Are familiar with accessibility principles and best practices. The purpose of this reference is to help you discover all of the tools available in DevTools that can help you examine a page's accessibility. See Navigating Chrome DevTools With Assistive Technology if you're looking for help on navigating DevTools with an assistive technology like a screen reader.

Overview of accessibility features in Chrome DevTools

This section explains how DevTools fits into your overall accessibility toolkit. When determining whether a page is accessible, you need to have 2 general questions in mind: Can I navigate the page with a keyboard or screen reader? Are the page's elements properly marked up for screen readers? In general, DevTools can help you fix errors related to question #2, because these errors are easy to detect in an automated fashion. Question #1 is just as important, but unfortunately DevTools can't help you there. The only way to find errors related to question #1 is to try using a page with a keyboard or screen reader yourself. See How To Do An Accessibility Review to learn more.

Audit a page's accessibility

In general, use the Audits panel to determine if: A page is properly marked up for screen readers. The text elements on a page have sufficient contrast ratios. See also View the contrast ratio of a text element in the Color Picker. To audit a page: Go to the URL that you want to audit. In DevTools, click the Audits tab. DevTools shows you various configuration options. Figure 1. Configuring audits Note: The screenshots in this section were taken with version 69 of Chrome. You can check what version you're running at chrome://version. The Audits panel UI looks different in earlier versions of Chrome, but the general workflow is the same. For Device, select Mobile if you want to simulate a mobile device. This option changes differently your user agent string and resizes the viewport. If the mobile version of the page displays differently than the desktop version, this option could have a significant effect on the results of your audit. In the Audits section, make sure that Accessibility is enabled. Disable the other categories if you want to exclude them from your report. Leave them enabled if you want to discover other ways to improve the quality of your page. The Throttling section lets you throttle the network and CPU, which is useful when analyzing load performance. This option should be irrelevant to your accessibility score, so you can use whatever you prefer. The Clear Storage checkbox lets you clear all storage before loading the page, or preserve storage between page loads. This option is also probably irrelevant to your accessibility score, so you can use whatever you prefer. Click Run Audits. After 10 to 30 seconds, DevTools provides a report. Your report gives you various tips on how to improve the page's accessibility. Figure 2. A report Click an audit to learn more about it. Figure 3. More information about an audit Click Learn More to view that audit's documentation. Figure 4. Viewing an audit's documentation

 See also: aXe extension

You may prefer to use the aXe extension rather than the Audits panel. They generally provide the same information, since aXe is the underlying engine that powers the Audits panel. The aXe extension has a different UI and describes audits slightly differently. One advantage that the aXe extension has over the Audits panel is that it lets you inspect and highlight failing nodes. Figure 5. The aXe extension

The Accessibility pane

The Accessibility pane is where you can view the accessibility tree, ARIA attributes, and computed accessibility properties of DOM nodes. To open the Accessibility pane: Click the Elements tab. In the DOM Tree, select the element which you want to inspect. Click the Accessibility tab. This tab may be hidden behind the More Tabs button. Figure 6. Inspecting the h1 element of the DevTools homepage in the Accessibility pane

 View an element's position in the accessibility tree

The accessibility tree is a subset of the DOM tree. It only contains elements from the DOM tree that are relevant and useful for displaying the page's contents in a screen reader. Inspect an element's position in the accessibility tree from the Accessibility pane. Figure 7. The Accessibility Tree section

 View an element's ARIA attributes

ARIA attributes ensure that screen readers have all of the information that they need in order to properly represent a page's contents. View an element's ARIA attributes in the Accessibility pane. Figure 8. The ARIA Attributes section

 View an element's computed accessibility properties

Note: If you're looking for computed CSS properties, see the Computed tab. Some accessibility properties are dynamically calculated by the browser. These properties can be viewed in the Computed Properties section of the Accessibility pane. View an element's computed accessibility properties in the Accessibility pane. Figure 9. The Computed (Accessibility) Properties section

View the contrast ratio of a text element in the Color Picker

Some people with low vision don't see areas as very bright or very dark. Everything tends to appear at about the same brightness, which makes it hard to distinguish outlines and edges. Contrast ratio measures the difference in brightness between the foreground and background of text. If your text has a low contrast ratio, then these low vision users may literally experience your site as a blank screen. The Color Picker can help you make sure that your text meets recommended contrast ratio levels: Click the Elements tab. In the DOM Tree, select the text element that you want to inspect. Figure 10. Inspecting a paragraph in the DOM Tree In the Styles pane, click the color square next to the element's color value. Figure 11. The color property of the element Check the Contrast Ratio section of the Color Picker. One checkmark means that the element meets the minimum recommendation. Two checkmarks means that it meets the enhanced recommendation. Figure 12. The Contrast Ratio section of the Color Picker shows 2 checkmarks and a value of 16.10 Click the Contrast Ratio section to see more information. A line appears in the visual picker at the top of the Color Picker. If the current color meets recommendations, then anything on the same side of the line also meets recommendations. If the current color does not meet recommendations, then anything on the same side also does not meet recommendations. Figure 13. The Contrast Ratio Line in the visual picker Improve article


Navigate Chrome DevTools with assistive technology

This guide aims to help users who primarily rely on assistive technology like screen readers access and use Chrome DevTools. Chrome DevTools is a suite of web developer tools built into the Google Chrome browser. See Accessibility Reference if you're looking for DevTools features related to improving the accessibility of a web page. The accessibility of DevTools is a work-in-progress. Some panels and tabs work better with assistive technology than others. This guide walks you through the panels which are the most accessible and highlights specific issues you may encounter along the way.

Overview

Before starting, it helps to have a mental model of how the DevTools UI is structured. DevTools is divided into a series of panels which are organized into an ARIA tablist. For example: The Elements panel lets you view and change DOM nodes or CSS. The Console panel lets you read JavaScript logs and live edit objects. Within the content area of each panel, there are a number of different tools, often referred to as tabs or panes in the documentation. For instance, the Elements panel contains additional tabs to inspect event listeners, the accessibility tree, and much more. The distinction between tabs and panes is somewhat arbitrary. The only reason you'll see one term or the other is to maintain consistency with the rest of the official DevTools documentation.

Keyboard shortcuts

The DevTools Keyboard Shortcuts reference is a helpful cheatsheet. Be sure to bookmark it and refer back to it as you explore the different panels.

Open DevTools

To get started, read through Open Chrome DevTools. There are a number of ways to open DevTools, either through keyboard shortcuts or menu items.

Navigate between panels

 Navigate by keyboard

With DevTools open, press Control+] or Command+] (Mac) to focus the next panel. Press Control+[ or Command+[ (Mac) to focus the previous panel. It's also possible to use Shift+Tab to move focus into a panel's tablist and use the arrow keys to change panels, though it may be faster to use the previously mentioned shortcuts.

Known issues

Some panels, such as the Console and Performance panels, may move focus into their content area as soon as they are activated. This can make navigating by arrow keys difficult. The selected panel's name is announced, but only after it has read the focused content in the panel. This can make it very easy to miss.

 Navigate by Command Menu

To focus a specific panel, use the Command Menu: With DevTools open, press Control+Shift+P or Command+Shift+P (Mac) to open the Command Menu. The Command Menu is a fuzzy search autocomplete combobox. Type the name of the panel you'd like to open, then use the Down Arrow keyboard to navigate to the correct option. Press Enter to run a command. For example, to open the Elements panel: Open the Command Menu. Type E then L. The Panel > Show Elements option is selected. Press Enter to run the command that opens the panel. Opening a panel this way directs focus to the contents of the panel itself. In the case of the Elements panel, focus moves into the DOM Tree.

Elements panel

 Inspect an element on the page

Navigate to the element you want to inspect using the screen reader's cursor. Simulate a right-mouse click on the element to open the context menu. Choose the Inspect option. This opens the Elements panel and focuses the element in the DOM Tree. The DOM Tree is laid out as an ARIA tree. See Navigate the DOM Tree with a keyboard for an example.

 Copy the code for an element in the DOM Tree

With focus on a node in the DOM Tree, bring up the right-click context menu. Expand the Copy option. Select Copy outerHTML.

Known issues

Copy outerHTML often doesn't select the current node but instead selects its parent node. However, the contents of the element should still be in the copied outerHTML.

 Modify the attributes of an element in the DOM Tree

With focus on a node in the DOM Tree, press Enter to make it editable. Press Tab to move between attribute values. When you hear "space" you are inside of an empty text input and can type a new attribute value. Press Control+Enter or Command+Enter (Mac) to accept the change and hear the entire contents of the element.

Known issues

When you type into the text input you get no feedback. If you make a typo and use the arrow keys to explore your input you also get no feedback. The easiest way to check your work is to accept the change, then listen for the entire element to be announced.

 Edit the HTML of an element in the DOM Tree

With focus on a node in the DOM Tree, press Enter to make it editable. Press Tab to move between attribute values. When you hear the element's name, for instance, "h2", you are inside of a text input and may change the element's type. Press Control+Enter or Command+Enter (Mac) to accept the change. For example, typing h3 and pressing Control+Enter or Command+Enter (Mac) changes the element's start and end tags to h3.

Elements panel tabs

The Elements panel contains additional tabs for inspecting things like the CSS applied to an element or its place in the accessibility tree. With focus on a node in the DOM Tree, press Tab until you hear that the Styles pane is selected. Use the Right Arrow to explore other available tabs. The DOM Tree turns elements with href attributes into focusable links, so you may need to press Tab more than once to reach the Styles pane.

 Known issues

The DOM Breakpoints and Properties tabs are not keyboard accessible.

 Styles pane

In the Styles pane you'll find controls for filtering styles, toggling element states (such as :active and :focus), toggling classes, and adding new classes. There is also a powerful style inspection tool to explore and modify styles currently applied to the element that's in focus in the DOM Tree. The key concept to understand about the Styles pane is that it only shows styles for the currently-selected node in the DOM Tree. For example, suppose you're done inspecting the styles of a <header> node, and now you want to look at the styles for a <footer> node. To do that, you first need to select the <footer> node in the DOM Tree. You might find it faster to use the Inspect workflow to inspect a node that's in the general vicinity of the footer node (such as a link within the footer), which focuses the DOM Tree, and then use your keyboard to navigate to the exact node that you're interested in.

Navigate the Styles pane

Because all of the style tools connect in one way or another back to the Styles pane, it makes sense to become an expert in this tool first. With focus on the Styles pane, press Tab to move focus inside and explore its contents. Press Tab until the first style becomes active. If you're using a screen reader this first style will be announced as "element.style {}". Press Down Arrow to navigate the list of styles in order of specificity. A screen reader announces each style starting with the name of the CSS file, the line number that the style appears on, and the style name itself. For example: "main.css:233 .card__img {}" Press Enter to inspect a style in more detail. Focus begins on an editable version of the style name. Press Tab to move between editable versions of each CSS property and their corresponding values. At the end of each style block is a blank editable text field which you may use to add additional CSS properties. You may continue to press Tab to move through the list of styles, or press Escape to exit this mode and go back to navigating by arrow keys. Be sure to read through the Styles pane keyboard reference for additional shortcuts.
Known Issues
If you use the Filter editable text field you will no longer be able to navigate the list of styles.

Toggle element state

To toggle an element's state, such as :active or :focus: Navigate to the Styles pane and press Tab until the Toggle Element State button has focus. Press Enter to expand the collection of element states. The element states are presented as a group of checkboxes. Press Tab until the first state, :active, has focus. Press Space to enable it. If the currently-selected element in the DOM Tree has an :active style, it's now applied. Continue pressing Tab to explore all of the available states.

Add an exiting class

Adjacent to the Toggle Element State button is the Element Classes button. Move focus to it by pressing Tab then Enter. Focus moves into an edit text field labeled Add New Class. The Element Classes button is primarily used for adding existing classes to an element. For example, if your stylesheet contained a helper class named .clearfix you could press . inside of the edit text field to see a suggestion list of classes and use the Down Arrow to find the .clearfix suggestion. Or type the class name out yourself and press Enter to apply it.

Add a new style rule

Adjacent to the Element Classes button is the New Style Rule button. Move focus to it by pressing Tab and press Enter. Focus moves into an editable text field inside of the style inspector. The initial text content of the field is the tag name of the element that is selected in the DOM Tree. You may type any class name you want into this field and then press Tab to assign CSS properties to it.

 Computed tab

With focus on the Computed tab, press Tab to move focus inside and explore its contents. Within the Computed tab there are controls for exploring which CSS properties are actually applied to an element in order of specificity.

Explore all computed styles

Press Tab until you reach the collection of computed styles. These are presented as an ARIA tree. Expanding a listbox reveals which CSS selectors are applying the computed style. These selectors are organized by specificity. A screen reader announces the computed value, which CSS selector is currently matching, the filename of the stylesheet that contains the selector, and the line number for the selector.

Known issues

If you use the Filter text field you will no longer be able to inspect styles.

 Event listeners tab

From within the Elements panel you may inspect the event listeners applied to an element using the Event Listeners tab. With focus on the Styles pane, press the Right Arrow to navigate to the Event Listeners tab.

Explore event listeners

Event listeners are presented as an ARIA tree. You may use the arrow keys to navigate them. A screen reader announces the name of the DOM object that the event listener is attached to, as well as the file name where the event listener is defined and its line number.

 Accessibility pane

With focus on the Accessibility pane, press Tab to move focus inside and explore its contents. Within the Accessibility pane there are controls for exploring the accessibility tree, the ARIA attributes applied to an element, and its computed accessibility properties.

Accessibility Tree

The Accessibility Tree is presented as an ARIA tree where each treeitem corresponds to an element in the DOM. The tree announces the computed role for the selected node. Generic elements like div and span are announced as "GenericContainer" in the tree. Use the arrow keys to traverse the tree and explore parent-child relationships.

Known issues

The type of ARIA tree used by the Accessibility pane may not be properly exposed in Chrome for macOS screen readers like VoiceOver. Subscribe to Chromium issue #868480 to be informed about progress on this issue. The ARIA Attributes and Computed Properties sections are marked up as ARIA trees, but they do not currently have focus management so they are not keyboard operable.

Audits panel

The Audits panel let's you run a series of tests against a site to check for common issues related to performance, accessibility, SEO, and a number of other categories.

 Configure and run an audit

When the Audits panel is first opened, focus is placed on the Run Audit button at the end of the form. By default the form is configured to run audits for every category using mobile emulation on a simulated 3G connection. Use Shift+Tab or navigate back in Browse mode to change the audit settings. When you're ready to run the audit, navigate back to the Run Audit button and press Enter. Focus moves into a modal window with a Cancel button which allows you to exit the audit. You may hear a series of earcons as the audit runs and refreshes the page multiple times.

Known issues

The different sections of the configuration form are not currently marked up with a fieldset element. It may be easier to navigate them in Browse mode to figure out which controls are associated with each section. There is no earcon or live region announcement when the audit is finished running. Generally it takes about 30 seconds, after which you should be able to navigate to the results. Using Browse mode may be the easiest way to reach the results.

 Navigate the audit report

The audit report is organized into sections that correspond with each of the audit categories. The report opens with a list of scores for each category. These scores are also links which can be used to skip to the relevant sections. Within each section are expandable details elements, which contain information relating to passed or failed audits. By default, only failing audits are shown. Each section ends with a final details element which contains all of the passed audits. To run a new audit, use Shift+Tab to exit the report and look for the Perform An Audit button. Improve article


Track element focus

Suppose that you're testing the keyboard navigation accessibility of a page. When navigating the page with the Tab key, the focus ring sometimes disappears because the element that has focus is hidden. To track the focused element in DevTools: Open the Console. Click Create Live Expression . Figure 1. Creating a Live Expression. Type document.activeElement. Click outside of the Live Expression UI to save. The value that you see below document.activeElement is the result of the expression. Since that expression always represents the focused element, you now have a way to always keep track of which element has focus. Hover over the result to highlight the focused element in the viewport. Right-click the result and select Reveal in Elements panel to show the element in the DOM Tree on the Elements panel. Right-click the result and select Store as global variable to create a variable reference to the node that you can use in the Console. Improve article


Remote debug Android devices

Remote debug live content on an Android device from your Windows, Mac, or Linux computer. This tutorial teaches you how to: Set up your Android device for remote debugging, and discover it from your development machine. Inspect and debug live content on your Android device from your development machine. Screencast content from your Android device onto a DevTools instance on your development machine. Figure 1. Remote Debugging lets you inspect a page running on an Android device from your development machine.

Step 1: Discover your Android device

The workflow below works for most users. See Troubleshooting: DevTools is not detecting the Android device for more help. Open the Developer Options screen on your Android. See Configure On-Device Developer Options. Select Enable USB Debugging. On your development machine, open Chrome. Go to chrome://inspect#devices. Make sure that the Discover USB devices checkbox is enabled. Figure 2. The Discover USB Devices checkbox is enabled Connect your Android device directly to your development machine using a USB cable. The first time you do this, you usually see that DevTools has detected an offline device. If you see the model name of your Android device, then DevTools has successfully established the connection to your device. Continue to Step 2. Figure 3. The Remote Target has successfully detected an offline device that is pending authorization If your device is showing up as Offline, accept the Allow USB Debugging permission prompt on your Android device.

 Troubleshooting: DevTools is not detecting the Android device

Make sure that your hardware is set up correctly: If you're using a USB hub, try connecting your Android device directly to your development machine instead. Try unplugging the USB cable between your Android device and development machine, and then plugging it back in. Do it while your Android and development machine screens are unlocked. Make sure that your USB cable works. You should be able to inspect files on your Android device from your development machine. Make sure that your software is set up correctly: If your development machine is running Windows, try manually installing the USB drivers for your Android device. See Install OEM USB Drivers. Some combinations of Windows and Android devices (especially Samsung) require extra set up. See Chrome DevTools Devices does not detect device when plugged in. If you don't see the Allow USB Debugging prompt on your Android device try: Disconnecting and then re-connecting the USB cable while DevTools is in focus on your development machine and your Android homescreen is showing. In other words, sometimes the prompt doesn't show up when your Android or development machine screens are locked. Updating the display settings for your Android device and development machine so that they never go to sleep. Setting Android's USB mode to PTP. See Galaxy S4 does not show Authorize USB debugging dialog box. Select Revoke USB Debugging Authorizations from the Developer Options screen on your Android device to reset it to a fresh state. If you find a solution that is not mentioned in this section or in Chrome DevTools Devices does not detect device when plugged in, please add an answer to that Stack Overflow question, or open an issue in the webfundamentals repository!

Step 2: Debug content on your Android device from your development machine

Open Chrome on your Android device. In the chrome://inspect/#devices, you see your Android device's model name, followed by its serial number. Below that, you can see the version of Chrome that's running on the device, with the version number in parentheses. Each open Chrome tab gets its own section. You can interact with that tab from this section. If there are any apps using WebView, you see a section for each of those apps, too. In Figure 5 there are no tabs or WebViews open. Figure 4. A connected remote device In the Open tab with url text box, enter a URL and then click Open. The page opens in a new tab on your Android device. Click Inspect next to the URL that you just opened. A new DevTools instance opens. The version of Chrome running on your Android device determines the version of DevTools that opens on your development machine. So, if your Android device is running a very old version of Chrome, the DevTools instance may look very different than what you're used to.

 More actions: pause, focus, reload, or close a tab

Below the URL you can find a menu to pause, focus, reload or close a tab. Figure 5. The menu for pausing, reloading, focusing, or closing a tab

 Inspect elements

Go to the Elements panel of your DevTools instance, and hover over an element to highlight it in the viewport of your Android device. You can also tap an element on your Android device screen to select it in the Elements panel. Click Select Element on your DevTools instance, and then tap the element on your Android device screen. Note that Select Element is disabled after the first touch, so you need to re-enable it every time you want to use this feature.

 Screencast your Android screen to your development machine

Click Toggle Screencast to view the content of your Android device in your DevTools instance. You can interact with the screencast in multiple ways: Clicks are translated into taps, firing proper touch events on the device. Keystrokes on your computer are sent to the device. To simulate a pinch gesture, hold Shift while dragging. To scroll, use your trackpad or mouse wheel, or fling with your mouse pointer. Some notes on screencasts: Screencasts only display page content. Transparent portions of the screencast represent device interfaces, such as the Chrome address bar, the Android status bar, or the Android keyboard. Screencasts negatively affect frame rates. Disable screencasting while measuring scrolls or animations to get a more accurate picture of your page's performance. If your Android device screen locks, the content of your screencast disappears. Unlock your Android device screen to automatically resume the screencast. Improve article


Access local servers

Host a site on a development machine web server, then access the content from an Android device. With a USB cable and Chrome DevTools, you can run a site from a development machine and then view the site on an Android device.

Summary

Port forwarding enables you to view content from your development machine's web server on your Android device. If your web server is using a custom domain, you can set up your Android device to access the content at that domain with custom domain mapping.

Set up port forwarding

Port forwarding enables your Android device to access content that's being hosted on your development machine's web server. Port forwarding works by creating a listening TCP port on your Android device that maps to a TCP port on your development machine. Traffic between the ports travel through the USB connection between your Android device and development machine, so the connection doesn't depend on your network configuration. To enable port forwarding: Set up remote debugging between your development machine and your Android device. When you're finished, you should see your Android device in the list. Click Port forwarding button. localhost:8080 is set up by default. Check Enable port forwarding. If you want to set up other ports, follow the steps 4 and 5. Otherwise skip to step 6. In the Port textfield on the left, enter the localhost port number from which you want to be able to access the site on your Android device. For example, if you wanted to access the site from localhost:5000 you would enter 5000. In the IP address and port textfield on the right, enter the IP address or hostname on which your site is running on your development machine's web server, followed by the port number. For example, if your site is running on localhost:7331 you would enter localhost:7331. Click Done. Port forwarding is now set up. You can see a status indicator of the port forward at the top as well as besides the device name. To view the content, open up Chrome on your Android device and go to the localhost port that you specified in the Device port field. For example, if you entered 5000 in the field, then you would go to localhost:5000.

Map to custom local domains

Custom domain mapping enables you to view content on an Android device from a web server on your development machine that is using a custom domain. For example, suppose that your site uses a third-party JavaScript library that only works on the allow-listed domain chrome.devtools. So, you create an entry in your hosts file on your development machine to map this domain to localhost (i.e. 127.0.0.1 chrome.devtools). After setting up custom domain mapping and port forwarding, you'll be able to view the site on your Android device at the URL chrome.devtools.

 Set up port forwarding to proxy server

To map a custom domain you must run a proxy server on your development machine. Examples of proxy servers are Charles, Squid, and Fiddler. To set up port forwarding to a proxy: Run the proxy server and note the port that it's using. Note: The proxy server and your web server must run on different ports. Set up port forwarding to your Android device. For the local address field, enter localhost: followed by the port that your proxy server is running on. For example, if it's running on port 8000, then you would enter localhost:8000. In the device port field enter the number that you want your Android device to listen on, such as 3333.

 Configure proxy settings on your device

Next, you need to configure your Android device to communicate with the proxy server. On your Android device go to Settings > Wi-Fi. Long-press the name of the network that you are currently connected to. Note: Proxy settings apply per network. Tap Modify network. Tap Advanced options. The proxy settings display. Tap the Proxy menu and select Manual. For the Proxy hostname field, enter localhost. For the Proxy port field, enter the port number that you entered for device port in the previous section. Tap Save. With these settings, your device forwards all of its requests to the proxy on your development machine. The proxy makes requests on behalf of your device, so requests to your customized local domain are properly resolved. Now you can access custom domains on your Android device Android just as you would on the development machine. If your web server is running off of a non-standard port, remember to specify the port when requesting the content from your Android device. For example, if your web server is using the custom domain chrome.devtools on port 7331, when you view the site from your Android device you should be using the URL chrome.devtools:7331. Tip: To resume normal browsing, remember to revert the proxy settings on your Android device after you disconnect from the development machine. Improve article


Remote debugging WebViews

Debug WebViews in your native Android apps using Chrome Developer Tools. On Android 4.4 (KitKat) or later, use DevTools to debug WebView content in native Android applications.

Summary

Enable WebView debugging in your native Android app; debug WebViews in Chrome DevTools. Access list of debug-enabled WebViews via chrome://inspect. Debugging WebViews is the same as debugging a web page through remote debugging.

Configure WebViews for debugging

WebView debugging must be enabled from within your application. To enable WebView debugging, call the static method setWebContentsDebuggingEnabled on the WebView class. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
This setting applies to all of the application's WebViews. Tip: WebView debugging is not affected by the state of the debuggable flag in the application's manifest. If you want to enable WebView debugging only when debuggable is true, test the flag at runtime. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
}

Open a WebView in DevTools

The chrome://inspect page displays a list of debug-enabled WebViews on your device. To start debugging, click inspect below the WebView you want to debug. Use DevTools as you would for a remote browser tab. The gray graphics listed with the WebView represent its size and position relative to the device's screen. If your WebViews have titles set, the titles are listed as well.

Troubleshooting

Can't see your WebViews on the chrome://inspect page? Verify that WebView debugging is enabled for your app. On your device, open the app with the WebView you want to debug. Then, refresh the chrome://inspect page. Improve article


Inspect JavaScript ArrayBuffer with the Memory inspector

This feature is available from Chrome 91 onwards. You can check your version with chrome://version/. Use the new Memory inspector to inspect an ArrayBuffer in JavaScript, as well as a WebAssembly.Memory.

Open the Memory Inspector

There are a few ways to open the Memory inspector.

 Open from the menu

Open DevTools. Click More Options

 Open during debugging

Open a page with JavaScript ArrayBuffer. We will be using this demo page. Open DevTools. Open the demo-js.js file in the Sources panel, set a breakpoint at line 18. Refresh the page. Expand the Scope section on the right Debugger pane. You can open the Memory inspector: From the icon. Clicking on the icon next to the buffer property, or From the context menu. Right click on the buffer property and select Reveal in Memory Inspector panel.

 Inspect multiple objects

You can inspect DataView or TypedArray as well. For example, b2 is a TypedArray. To inspect that, right click on the b2 property and select Reveal in Memory Inspector panel (No icon for TypedArray or DataView yet). A new tab is opened in the Memory inspector. Please note that you can inspect multiple objects at once.

The Memory inspector

The Memory inspector consists of 3 main areas:

 Navigation bar

The address input shows the current byte address in hex format. You can input a new value to jump to a new location in the memory buffer. For example, try type 0x00000008. Memory buffers could be longer than a page. Instead of scrolling through, you can use the left and right button to navigate. The buttons on the left allow a forward/backward navigation. By default, the buffer is automatically updated on stepping. In the case it's not, the refresh button gives you the option to refresh the memory and update its contents.

 Memory buffer

From the left, the address is displayed in hex format. The memory is also shown in hex format, each byte separated by a space. The currently selected byte is highlighted. You can click on the byte or navigate with keyboard (left, right, up, down). An ASCII representation of the memory is shown on the right side. A highlight shows the corresponding value to the selected bits on the byte. Similar to memory, you can click on the byte or navigate with keyboard (left, right, up, down).

 Value inspector

A top toolbar features a button to switch between big and little endian and to open the settings. Open the settings to select which value types they want to see per default in the inspector. The main area shows all the value interpretations as per the settings. By default, all are shown. The encoding is clickable. You can switch between dec, hex, oct for integer and sci, dec for floats.

Inspecting memory

Let's inspect the memory together. Follow these steps to start the debugging. Change the address to 0x00000027 in the address input. Observe the ASCII representation and the value interpretations. All values are empty at the moment. Notice the blue Jump to address button next to Pointer 32-bit and Pointer 64-bit. You can click on it to jump to the address. The buttons are grayed out and not clickable if the addresses are not valid. Click on Resume script execution to step through the code. Notice the ASCII representation is now updated. All the value interpretations are updated as well. Let's customize the Value inspector to show only floating point. Click on the settings button and check only Float 32-bit and Float 64-bit. Let's change the encoding from dec to sci. Notice the value representations are updated accordingly. Try to navigate the memory buffer with your keyboard or using the navigation bar. Repeat step 4 to observe values changes.

WebAssembly memory inspection

For Wasm memory inspection, the process is similar to the JavaScript one. Open this demo page. In the Sources panel, open memory-write.wasm and set a breakpoint at line 5. Refresh the page. In the debugger pane, expand the Scope. In the Scope section, expand the Module. Click on the icon next to the $imports.memory property to reveal the Memory inspector. Read this article to learn more on debugging WebAssembly with modern tools. Improve article


Fix memory problems

Learn how to use Chrome and DevTools to find memory issues that affect page performance, including memory leaks, memory bloat, and frequent garbage collections.

Summary

Find out how much memory your page is currently using with the Chrome Task Manager. Visualize memory usage over time with Timeline recordings. Identify detached DOM trees (a common cause of memory leaks) with Heap Snapshots. Find out when new memory is being allocated in your JS heap with Allocation Timeline recordings.

Overview

In the spirit of the RAIL performance model, the focus of your performance efforts should be your users. Memory issues are important because they are often perceivable by users. Users can perceive memory issues in the following ways: A page's performance gets progressively worse over time. This is possibly a symptom of a memory leak. A memory leak is when a bug in the page causes the page to progressively use more and more memory over time. A page's performance is consistently bad. This is possibly a symptom of memory bloat. Memory bloat is when a page uses more memory than is necessary for optimal page speed. A page's performance is delayed or appears to pause frequently. This is possibly a symptom of frequent garbage collections. Garbage collection is when the browser reclaims memory. The browser decides when this happens. During collections, all script execution is paused. So if the browser is garbage collecting a lot, script execution is going to get paused a lot.

 Memory bloat: how much is "too much"?

A memory leak is easy to define. If a site is progressively using more and more memory, then you've got a leak. But memory bloat is a bit harder to pin down. What qualifies as "using too much memory"? There are no hard numbers here, because different devices and browsers have different capabilities. The same page that runs smoothly on a high-end smartphone might crash on a low-end smartphone. The key here is to use the RAIL model and focus on your users. Find out what devices are popular with your users, and then test out your page on those devices. If the experience is consistently bad, the page may be exceeding the memory capabilities of those devices.

Monitor memory use in realtime with the Chrome Task Manager

Use the Chrome Task Manager as a starting point to your memory issue investigation. The Task Manager is a realtime monitor that tells you how much memory a page is currently using. Press Shift+Esc or go to the Chrome main menu and select More tools > Task manager to open the Task Manager. Right-click on the table header of the Task Manager and enable JavaScript memory. These two columns tell you different things about how your page is using memory: The Memory column represents native memory. DOM nodes are stored in native memory. If this value is increasing, DOM nodes are getting created. The JavaScript Memory column represents the JS heap. This column contains two values. The value you're interested in is the live number (the number in parentheses). The live number represents how much memory the reachable objects on your page are using. If this number is increasing, either new objects are being created, or the existing objects are growing.

Visualize memory leaks with Timeline recordings

You can also use the Timeline panel as another starting point in your investigation. The Timeline panel helps you visualize a page's memory use over time. Open the Timeline panel on DevTools. Enable the Memory checkbox. Make a recording. Tip: It's a good practice to start and end your recording with a forced garbage collection. Click the collect garbage button ( ) while recording to force garbage collection. To demonstrate Timeline memory recordings, consider the code below: var x = [];

function grow() {
for (var i = 0; i < 10000; i++) {
document.body.appendChild(document.createElement('div'));
}
x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);
Every time that the button referenced in the code is pressed, ten thousand div nodes are appended to the document body, and a string of one million x characters is pushed onto the x array. Running this code produces a Timeline recording like the following screenshot: First, an explanation of the user interface. The HEAP graph in the Overview pane (below NET) represents the JS heap. Below the Overview pane is the Counter pane. Here you can see memory usage broken down by JS heap (same as HEAP graph in the Overview pane), documents, DOM nodes, listeners, and GPU memory. Disabling a checkbox hides it from the graph. Now, an analysis of the code compared with the screenshot. If you look at the node counter (the green graph) you can see that it matches up cleanly with the code. The node count increases in discrete steps. You can presume that each increase in the node count is a call to grow(). The JS heap graph (the blue graph) is not as straightforward. In keeping with best practices, the first dip is actually a forced garbage collection (achieved by pressing the collect garbage button). As the recording progresses you can see that the JS heap size spikes. This is natural and expected: the JavaScript code is creating the DOM nodes on every button click and doing a lot of work when it creates the string of one million characters. The key thing here is the fact that the JS heap ends higher than it began (the "beginning" here being the point after the forced garbage collection). In the real world, if you saw this pattern of increasing JS heap size or node size, it would potentially mean a memory leak.

Discover detached DOM tree memory leaks with Heap Snapshots

A DOM node can only be garbage collected when there are no references to it from either the page's DOM tree or JavaScript code. A node is said to be "detached" when it's removed from the DOM tree but some JavaScript still references it. Detached DOM nodes are a common cause of memory leaks. This section teaches you how to use DevTools' heap profilers to identify detached nodes. Here's a simple example of detached DOM nodes. var detachedTree;

function create() {
var ul = document.createElement('ul');
for (var i = 0; i < 10; i++) {
var li = document.createElement('li');
ul.appendChild(li);
}
detachedTree = ul;
}

document.getElementById('create').addEventListener('click', create);
Clicking the button referenced in the code creates a ul node with ten li children. These nodes are referenced by the code but do not exist in the DOM tree, so they're detached. Heap snapshots are one way to identify detached nodes. As the name implies, heap snapshots show you how memory is distributed among your page's JS objects and DOM nodes at the point of time of the snapshot. To create a snapshot, open DevTools and go to the Profiles panel, select the Take Heap Snapshot radio button, and then press the Take Snapshot button. The snapshot may take some time to process and load. Once it's finished, select it from the lefthand panel (named HEAP SNAPSHOTS). Type Detached in the Class filter textbox to search for detached DOM trees. Expand the carats to investigate a detached tree. Nodes highlighted yellow have direct references to them from the JavaScript code. Nodes highlighted red do not have direct references. They are only alive because they are part of the yellow node's tree. In general, you want to focus on the yellow nodes. Fix your code so that the yellow node isn't alive for longer than it needs to be, and you also get rid of the red nodes that are part of the yellow node's tree. Click on a yellow node to investigate it further. In the Objects pane you can see more information about the code that's referencing it. For example, in the screenshot below you can see that the detachedTree variable is referencing the node. To fix this particular memory leak, you would study the code that uses detachedTree and ensure that it removes its reference to the node when it's no longer needed.

Identify JS heap memory leaks with Allocation Timelines

The Allocation Timeline is another tool that can help you track down memory leaks in your JS heap. To demonstrate the Allocation Timeline consider the following code: var x = [];

function grow() {
x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);
Every time that the button referenced in the code is pushed, a string of one million characters is added to the x array. To record an Allocation Timeline, open DevTools, go to the Profiles panel, select the Record Allocation Timeline radio button, press the Start button, perform the action that you suspect is causing the memory leak, and then press the stop recording button ( ) when you're done. As you're recording, notice if any blue bars show up on the Allocation Timeline, like in the screenshot below. Those blue bars represent new memory allocations. Those new memory allocations are your candidates for memory leaks. You can zoom on a bar to filter the Constructor pane to only show objects that were allocated during the specified timeframe. Expand the object and click on its value to view more details about it in the Object pane. For example, in the screenshot below, by viewing the details of the object that was newly allocated, you'd be able to see that it was allocated to the x variable in the Window scope.

Investigate memory allocation by function

Use the Record Allocation Profiler type to view memory allocation by JavaScript function. Select the Record Allocation Profiler radio button. If there is a worker on the page, you can select that as the profiling target using the dropdown menu next to the Start button. Press the Start button. Perform the actions on the page which you want to investigate. Press the Stop button when you have finished all of your actions. DevTools shows you a breakdown of memory allocation by function. The default view is Heavy (Bottom Up), which displays the functions that allocated the most memory at the top.

Spot frequent garbage collections

If your page appears to pause frequently, then you may have garbage collection issues. You can use either the Chrome Task Manager or Timeline memory recordings to spot frequent garbage collections. In the Task Manager, frequently rising and falling Memory or JavaScript Memory values represent frequent garbage collections. In Timeline recordings, frequently rising and falling JS heap or node count graphs indicate frequent garbage collections. Once you've identified the problem, you can use an Allocation Timeline recording to find out where memory is being allocated and which functions are causing the allocations. Improve article


Memory terminology

This section describes common terms used in memory analysis, and is applicable to a variety of memory profiling tools for different languages. The terms and notions described here refer to the Chrome DevTools Heap Profiler. If you have ever worked with either the Java, .NET, or some other memory profiler, then this may be a refresher.

Object sizes

Think of memory as a graph with primitive types (like numbers and strings) and objects (associative arrays). It might visually be represented as a graph with a number of interconnected points as follows: An object can hold memory in two ways: Directly by the object itself. Implicitly by holding references to other objects, and therefore preventing those objects from being automatically disposed by a garbage collector (GC for short). When working with the Heap Profiler in DevTools (a tool for investigating memory issues found under "Profiles"), you will likely find yourself looking at a few different columns of information. Two that stand out are Shallow Size and Retained Size, but what do these represent?

 Shallow size

This is the size of memory that is held by the object itself. Typical JavaScript objects have some memory reserved for their description and for storing immediate values. Usually, only arrays and strings can have a significant shallow size. However, strings and external arrays often have their main storage in renderer memory, exposing only a small wrapper object on the JavaScript heap. Renderer memory is all memory of the process where an inspected page is rendered: native memory + JS heap memory of the page + JS heap memory of all dedicated workers started by the page. Nevertheless, even a small object can hold a large amount of memory indirectly, by preventing other objects from being disposed of by the automatic garbage collection process.

 Retained size

This is the size of memory that is freed once the object itself is deleted along with its dependent objects that were made unreachable from GC roots. GC roots are made up of handles that are created (either local or global) when making a reference from native code to a JavaScript object outside of V8. All such handles can be found within a heap snapshot under GC roots > Handle scope and GC roots > Global handles. Describing the handles in this documentation without diving into details of the browser implementation may be confusing. Both GC roots and the handles are not something you need to worry about. There are lots of internal GC roots most of which are not interesting for the users. From the applications standpoint there are following kinds of roots: Window global object (in each iframe). There is a distance field in the heap snapshots which is the number of property references on the shortest retaining path from the window. Document DOM tree consisting of all native DOM nodes reachable by traversing the document. Not all of them may have JS wrappers but if they have the wrappers will be alive while the document is alive. Sometimes objects may be retained by debugger context and DevTools console (e.g. after console evaluation). Create heap snapshots with clear console and no active breakpoints in the debugger. The memory graph starts with a root, which may be the window object of the browser or the Global object of a Node.js module. You don't control how this root object is GC'd. Whatever is not reachable from the root gets GC. Note: Both the Shallow and Retained size columns represent data in bytes.

Objects retaining tree

The heap is a network of interconnected objects. In the mathematical world, this structure is called a graph or memory graph. A graph is constructed from nodes connected by means of edges, both of which are given labels. Nodes (or objects) are labelled using the name of the constructor function that was used to build them. Edges are labelled using the names of properties. Learn how to record a profile using the Heap Profiler. Some of the eye-catching things we can see in the Heap Profiler recording below include distance: the distance from the GC root. If almost all the objects of the same type are at the same distance, and a few are at a bigger distance, that's something worth investigating.

Dominators

Dominator objects are comprised of a tree structure because each object has exactly one dominator. A dominator of an object may lack direct references to an object it dominates; that is, the dominator's tree is not a spanning tree of the graph. In the diagram below: Node 1 dominates node 2 Node 2 dominates nodes 3, 4 and 6 Node 3 dominates node 5 Node 5 dominates node 8 Node 6 dominates node 7 In the example below, node #3 is the dominator of #10, but #7 also exists in every simple path from GC to #10. Therefore, an object B is a dominator of an object A if B exists in every simple path from the root to the object A.

V8 specifics

When profiling memory, it is helpful to understand why heap snapshots look a certain way. This section describes some memory-related topics specifically corresponding to the V8 JavaScript virtual machine (V8 VM or VM).

 JavaScript object representation

There are three primitive types: Numbers (e.g., 3.14159..) Booleans (true or false) Strings (e.g., 'Werner Heisenberg') They cannot reference other values and are always leafs or terminating nodes. Numbers can be stored as either: an immediate 31-bit integer values called small integers (SMIs), or heap objects, referred to as heap numbers. Heap numbers are used for storing values that do not fit into the SMI form, such as doubles, or when a value needs to be boxed, such as setting properties on it. Strings can be stored in either: the VM heap, or externally in the renderer's memory. A wrapper object is created and used for accessing external storage where, for example, script sources and other content that is received from the Web is stored, rather than copied onto the VM heap. Memory for new JavaScript objects is allocated from a dedicated JavaScript heap (or VM heap). These objects are managed by V8's garbage collector and therefore, will stay alive as long as there is at least one strong reference to them. Native objects are everything else which is not in the JavaScript heap. Native object, in contrast to heap object, is not managed by the V8 garbage collector throughout its lifetime, and can only be accessed from JavaScript using its JavaScript wrapper object. Cons string is an object that consists of pairs of strings stored then joined, and is a result of concatenation. The joining of the cons string contents occurs only as needed. An example would be when a substring of a joined string needs to be constructed. For example, if you concatenate a and b, you get a string (a, b) which represents the result of concatenation. If you later concatenated d with that result, you get another cons string ((a, b), d). Arrays - An Array is an Object with numeric keys. They are used extensively in the V8 VM for storing large amounts of data. Sets of key-value pairs used like dictionaries are backed up by arrays. A typical JavaScript object can be one of two array types used for storing: named properties, and numeric elements In cases where there is a very small number of properties, they can be stored internally in the JavaScript object itself. Map-an object that describes the kind of object and its layout. For example, maps are used to describe implicit object hierarchies for fast property access.

 Object groups

Each native objects group is made up of objects that hold mutual references to each other. Consider, for example, a DOM subtree where every node has a link to its parent and links to the next child and next sibling, thus forming a connected graph. Note that native objects are not represented in the JavaScript heap—that's why they have zero size. Instead, wrapper objects are created. Each wrapper object holds a reference to the corresponding native object, for redirecting commands to it. In its own turn, an object group holds wrapper objects. However, this doesn't create an uncollectable cycle, as GC is smart enough to release object groups whose wrappers are no longer referenced. But forgetting to release a single wrapper will hold the whole group and associated wrappers. Improve article


Record heap snapshots

Learn how to record heap snapshots with the Chrome DevTools heap profiler and find memory leaks. The Chrome DevTools heap profiler shows memory distribution by your page's JavaScript objects and related DOM nodes (see also Objects retaining tree). Use it to take JS heap snapshots, analyze memory graphs, compare snapshots, and find memory leaks.

Take a snapshot

On the Profiles panel, choose Take Heap Snapshot, then click Start or press Cmd + E or Ctrl + E: Snapshots are initially stored in the renderer process memory. They are transferred to the DevTools on demand, when you click on the snapshot icon to view it. After the snapshot has been loaded into DevTools and has been parsed, the number below the snapshot title appears and shows the total size of the reachable JavaScript objects: Note: Only reachable objects are included in snapshots. Also, taking a snapshot always starts with a garbage collection.

Clear snapshots

Remove snapshots (both from DevTools and renderers memory) by pressing the Clear all profiles icon: Closing the DevTools window will not delete profiles from the renderers memory. When reopening DevTools, all previously taken snapshots will reappear in the list of snapshots. Example: Try out this example of scattered objects and profile it using the Heap Profiler. You should see a number of (object) item allocations.

View snapshots

View snapshots from different perspectives for different tasks. Summary view shows objects grouped by the constructor name. Use it to hunt down objects (and their memory use) based on type grouped by constructor name. It's particularly helpful for tracking down DOM leaks. Comparison view displays difference between two snapshots. Use it to compare two (or more) memory snapshots of before and after an operation. Inspecting the delta in freed memory and reference count lets you confirm the presence and cause of a memory leak. Containment view allows exploration of heap contents. It provides a better view of object structure, helping analyze objects referenced in the global namespace (window) to find out what is keeping them around. Use it to analyze closures and dive into your objects at a low level. Dominators view shows the dominators tree and can be useful to find accumulation points. This view helps confirm that no unexpected references to objects are still hanging around and that deletion/garbage collection is actually working. To switch between views, use the selector at the bottom of the view: Note: Not all properties are stored on the JavaScript heap. Properties implemented using getters that execute native code aren't captured. Also, non-string values such as numbers are not captured.

 Summary view

Initially, a snapshot opens in the Summary view, displaying object totals, which can be expanded to show instances: Top-level entries are "total" lines. They display: Constructor represents all objects created using this constructor. Number of object instances is displayed in the # column. Shallow size column displays the sum of shallow sizes of all objects created by a certain constructor function. The shallow size is the size of memory held by an object itself (generally, arrays and strings have larger shallow sizes). See also Object sizes. Retained size column displays the maximum retained size among the same set of objects. The size of memory that can be freed once an object is deleted (and this its dependents made no longer reachable) is called the retained size. See also Object sizes. Distance displays the distance to the root using the shortest simple path of nodes. After expanding a total line in the upper view, all of its instances are displayed. For each instance, its shallow and retained sizes are displayed in the corresponding columns. The number after the @ character is the objects' unique ID, allowing you to compare heap snapshots on per-object basis. Remember that yellow objects have JavaScript references on them and red objects are detached nodes which are referenced from one with a yellow background. What do the various constructor (group) entries in the Heap profiler correspond to? (global property)–intermediate objects between a global object (like 'window') and an object referenced by it. If an object is created using a constructor Person and is held by a global object, the retaining path would look like [global] > (global property) > Person. This contrasts with the norm, where objects directly reference each other. We have intermediate objects for performance reasons. Globals are modified regularly and property access optimizations do a good job for non-global objects aren't applicable for globals. (roots)–The root entries in the retaining tree view are the entities that have references to the selected object. These can also be references created by the engine for its own purposes. The engine has caches which reference objects, but all such references are weak and won't prevent an object from being collected given that there are no truly strong references. (closure)–a count of references to a group of objects through function closures (array, string, number, regexp)–a list of object types with properties which reference an Array, String, Number or regular expression. (compiled code)–simply, everything related to compiled code. Script is similar to a function but corresponds to a <script> body. SharedFunctionInfos (SFI) are objects standing between functions and compiled code. Functions are usually have a context, while SFIs do not. HTMLDivElement, HTMLAnchorElement, DocumentFragment etc–references to elements or document objects of a particular type referenced by your code. Example: Try this demo page to understand how the Summary view can be used.

 Comparison view

Find leaked objects by comparing multiple snapshots to each other. To verify that a certain application operation doesn't create leaks (for example, usually a pair of direct and reverse operations, like opening a document, and then closing it, should not leave any garbage), you may follow the scenario below: Take a heap snapshot before performing an operation. Perform an operation (interact with a page in some way that you believe to be causing a leak). Perform a reverse operation (do the opposite interaction and repeat it a few times). Take a second heap snapshot and change the view of this one to Comparison, comparing it to snapshot 1. In the Comparison view, the difference between two snapshots is displayed. When expanding a total entry, added and deleted object instances are shown: demo page to get an idea how to use snapshot comparison for detecting leaks.

 Containment view

The Containment view is essentially a "bird's eye view" of your application's objects structure. It allows you to peek inside function closures, to observe VM internal objects that together make up your JavaScript objects, and to understand how much memory your application uses at a very low level. The view provides several entry points: DOMWindow objects are objects considered as "global" objects for JavaScript code. GC roots are the actual GC roots used by VM's garbage. GC roots can be comprised of built-in object maps, symbol tables, VM thread stacks, compilation caches, handle scopes, global handles. Native objects are browser objects "pushed" inside the JavaScript virtual machine to allow automation, for example, DOM nodes, CSS rules. demo page for finding out how to explore closures and event handlers using the view. A tip about closures It helps a lot to name the functions so you can easily distinguish between closures in the snapshot. For example, this example does not use named functions: function createLargeClosure() {
var largeStr = new Array(1000000).join('x');

var lC = function() { // this is NOT a named function
return largeStr;
};

return lC;
}
Whilst this example does: function createLargeClosure() {
var largeStr = new Array(1000000).join('x');

var lC = function lC() { // this IS a named function
return largeStr;
};

return lC;
}
heap allocations.

 Dominators view

The Dominators view shows the dominators tree for the heap graph. It looks similar to the Containment view, but lacks property names. This is because a dominator of an object may lack direct references to it; the dominators tree is not a spanning tree of the graph. But this only serves for good, as helps us to identify memory accumulation points quickly. Note: In Chrome Canary, Dominators view can be enabled by going to Settings > Show advanced heap snapshot properties and restarting the DevTools. retaining paths and dominators.

Look up color coding

Properties and property values of objects have different types and are colored accordingly. Each property has one of four types: a: property—regular property with a name, accessed via the . (dot) operator, or via brackets ([]) notation, e.g. [foo bar] 0: element—regular property with a numeric index, accessed via brackets ([]) notation a: context var - variable in a function context, accessible by its name from inside a function closure; a: system prop - property added by the JavaScript VM, not accessible from JavaScript code. Objects designated as Systemdo not have a corresponding JavaScript type. They are part of JavaScript VM's object system implementation. V8 allocates most of its internal objects in the same heap as the user's JS objects. So these are just v8 internals.

Find a specific object

To find an object in the collected heap you can search using Ctrl + F and give the object ID.

Uncover DOM leaks

The heap profiler has the ability to reflect bidirectional dependencies between browser native objects (DOM nodes, CSS rules) and JavaScript objects. This helps to discover otherwise invisible leaks happening due to forgotten detached DOM subtrees floating around. DOM leaks can be bigger than you think. Consider the following sample - when is the #tree GC? var select = document.querySelector;
var treeRef = select("#tree");
var leafRef = select("#leaf");
var body = select("body");

body.removeChild(treeRef);

//#tree can't be GC yet due to treeRef
treeRef = null;

//#tree can't be GC yet due to indirect
//reference from leafRef

leafRef = null;
//#NOW can be #tree GC
#leaf maintains a reference to it's parent (parentNode) and recursively up to #tree, so only when leafRef is nullified is the WHOLE tree under #tree a candidate for GC. DOM leaks being bigger than expected. To read more about DOM leaks and memory analysis fundamentals checkout Finding and debugging memory leaks with the Chrome DevTools by Gonzalo Ruiz de Villa. Example: Try this demo to play with detached DOM trees. Improve article


How to Use the Allocation Profiler Tool

Use the allocation profiler tool to find objects that aren't being properly garbage collected, and continue to retain memory.

How the tool works

The allocation profiler combines the detailed snapshot information of the heap profiler with the incremental updating and tracking of the Timeline panel. Similar to these tools, tracking objects' heap allocation involves starting a recording, performing a sequence of actions, then stop the recording for analysis. The tool takes heap snapshots periodically throughout the recording (as frequently as every 50 ms!) and one final snapshot at the end of the recording. Note: The number after the @ is an object ID that persists among multiple snapshots taken. This allows precise comparison between heap states. Displaying an object's address makes no sense, as objects are moved during garbage collections.

Enable allocation profiler

To begin using the allocation profiler: Make sure you have the latest Chrome Canary. Open the Developer Tools and click on the gear icon in the lower right. Now, open the Profiler panel, you should see a profile called "Record Heap Allocations"

Read a heap allocation profile

The heap allocation profile shows where objects are being created and identifies the retaining path. In the snapshot below, the bars at the top indicate when new objects are found in the heap. The height of each bar corresponds to the size of the recently allocated objects, and the color of the bars indicate whether or not those objects are still live in the final heap snapshot. Blue bars indicate objects that are still live at the end of the timeline, Gray bars indicate objects that were allocated during the timeline, but have since been garbage collected: In the snapshot below, an action was performed 10 times. The sample program caches five objects, so the last five blue bars are expected. But the leftmost blue bar indicates a potential problem. You can then use the sliders in the timeline above to zoom in on that particular snapshot and see the objects that were recently allocated at that point: Clicking on a specific object in the heap will show its retaining tree in the bottom portion of the heap snapshot. Examining the retaining path to the object should give you enough information to understand why the object was not collected, and you can make the necessary code changes to remove the unnecessary reference.

View memory allocation by function

You can also view memory allocation by JavaScript function. See Investigate memory allocation by function for more information. Improve article


Record, replay and measure user flows

Take a glance at the new Recorder panel (preview feature) with the video below. Use the Recorder panel to record, replay and measure user flows. This is a preview feature in Chrome 97. Our team is actively working on this feature and we are looking for your feedback for further enhancements.

Open the Recorder panel

Open DevTools. Click on More options > More tools > Recorder. Command Menu to open the Recorder panel.

Introduction

We will be using this coffee ordering demo page. Checkout is a common user flow among shopping websites. In the next sections, we will walk you through how to record, replay and audit the following checkout flow with the Recorder panel: Add a coffee to the cart. Add another coffee to the cart. Go to the cart page. Remove one coffee from the cart. Start the checkout process. Fill in payment details. Check out.

Record a user flow

Open this demo page. Click on the Start new recording button to begin. Enter "coffee checkout" in the Recording name textbox, then click on the Start a new recording button. The recording is started. The panel is showing Recording... indicating the recording is in progress. Click on Cappucino to add it to the cart. Click on Americano to add it to the cart. Notice that the Recorder shows the steps that you have performed so far. Go to the cart page. Remove Americano from the cart. Click on the Total: $19.00 button to start the checkout process. In the payment details form, fill in the Name and Email textboxes, and check the I would like to receive order updates and promotional messages. checkbox. Click on the Submit button to complete the checkout process. In the Recorder panel. Click End recording button to end the recording.

Replay a user flow

After recording a user flow, you can replay it by clicking on the Replay button. You can see the user flow replay on the page. The replay progress is shown in the Recorder panel as well. You can simulate a slow network connection by configuring the Replay settings. For example, expand the Replay settings, select Slow 3G in the Network dropdown. More settings might be supported in the future. Share with us the replay settings you would like to have!

Measure a user flow

You can measure the performance of a user flow by clicking on the Measure performance button. For example, checkout is a critical user flow of a shopping website. With the Recorder panel, you can record the checkout flow once and measure it regularly. Clicking on the Measure performance button will first trigger a replay of the user flow, then open the performance trace in the Performance panel. Learn how to analyze your page's runtime performance with the Performance panel. You can enable the Web Vitals checkbox in the Performance panel, to view the Web Vitals metrics, identify opportunities to improve your user browsing experience.

Edit user flows

Let's walk through the options to edit the user flows. On the top of the Recorder panel, there are options for you to: Add a new recording. Click on the + icon to add a new recording. View all recordings. The dropdown shows the list of saved recordings. Select the [number] recording(s) option to expand and manage the list of saved recordings. Export a recording. You can export the user flow as Puppeteer script to customize the script further. Delete a recording. Delete the selected recording.

Edit steps

Let's walk through the options to edit the steps within a workflow. Expand each step to see the details of the action. For example, expand the Click Element "Cappucino" step. The step above shows 2 selectors. The Recorder will automatically detect 2 selectors for most of the steps by default. When replaying the user flow, the Recorder will try to query the element with one of the selectors by sequence. For example, if the Recorder successfully queries the element with the first selector, it will skip the second selector and proceed to the next step. You can add or remove any selectors. For example, you can remove the selector #2 because just aria/Cappucino is sufficient in this case. Hover over the selector #2 and click on - to remove it. The selector is editable too. For example, if you want to select Mocha instead of Cappucino, you can edit the selector value to aria/Mocha instead. Replay the flow now, it should select Mocha instead of Cappucino. Try to edit other step properties such as type, target, value and more. There are options to add and remove steps too. This is useful if you want to add an extra step or remove an accidentally added step. Instead of re-recording the user flow, you can just edit it. Click on the 3-dot kebab menu next to the step to open the menu. For example, the Scroll event after the Mocha step is not necessary. You can select Remove step to remove it. Says, you want to wait until there are 9 coffees display on the page before performing any steps. In the Mocha step menu, select Add step before. A new step is created. Edit the step with the following details: type: waitForElement selector #1: .cup operator: == (click add operator button) count: 9 (click add count button) Replay the flow now to see the changes. Improve article


View and debug media players information

Use the Media Panel in Chrome DevTools to view information and debug the media players per browser tab.

Open the Media panel

The Media panel is the main place in DevTools for inspecting the media player of a page. Open DevTools. Click the More Options > More tools > Media to open the Media panel.

View media players information

Visit a page with a media player, such as https://youtu.be/e1gAyQuIFQo. You can now see a media player under the Players menu. Click on the player. The Properties tab displays the properties of the media player. Click on the Events tab to view all the media player events. Click on the Messages tab to view the media player message logs. You can filter the messages by log level or string. The Timeline tab is where you can view the media playback and buffer status live.

 Remote debugging

You can view the media players information on an Android device from your Windows, Mac, or Linux computer. Follow these steps to set up remote debugging. Now you can view the media players information remotely.

Hide and show media players

Sometimes there might be more than one media player on a page, or you might use the same browser tab browsing different pages, each with media players. You can choose to show or hide each media player for easier debugging experience. Browse to several different video pages using the same browser tab. Right click on one of the media players. You can choose to hide the selected player by select Hide player or select Hide all others to hide all the other players.

Export media player information

Right click on one of the media players. Select Save player info to download the player info as json. Improve article


Emulate authenticators and debug WebAuthn

Use the WebAuthn tab in Chrome DevTools to create and interact with software-based virtual authenticators.

Open the WebAuthn tab

Visit a page that uses WebAuthn, such as our demo page here - webauthndemo.appspot.com/ (please login to access the page). Open DevTools. Click More Options > More tools > WebAuthn to open the WebAuthn tab.

Enable the virtual authenticator environment

On the WebAuthn tab, click to enable the checkbox Enable virtual authenticator environment. Once enabled, you will see a new section New authenticator.

Add a virtual authenticator

On the New authenticator section, configure the options. Click on the Add button. You can now see a new section of your newly-created authenticator. The Authenticator section includes a Credentials table. The table is empty until a credential is registered to the authenticator.

 Register a new credential

To register a new credential, you need to have a web page that uses WebAuthn, for example our demo page here - webauthndemo.appspot.com/. On the demo page, click on Register new credential to register a new credential. A new credential is now added to the Credentials table in the WebAuthn tab. On the demo page, you can click the Authenticate button multiple times. Observe the Credentials table. The Sign Count of the credential will increase accordingly.

 Export and remove credentials

You can export or remove a credential by clicking the Export or Remove button.

Rename an authenticator

To rename an authenticator, click the Edit button beside the authenticator name. Edit the name, then click Enter to save the changes.

Set the active authenticator

A newly created authenticator will be set active automatically. DevTools supports only one active virtual authenticator at any point of time. Removing the currently active authenticator results in no authenticator being active. To set an authenticator as the active authenticator, select the Active radio button of an authenticator.

Remove a virtual authenticator

To remove a virtual authenticator, click the Remove button of the authenticator. Improve article


Edit files with Workspaces

Goal: This tutorial provides hands-on practice in setting up and using Workspaces so that you can use Workspaces in your own projects. Workspaces enable you to save changes that you make within DevTools to source code that's stored on your computer. Caution Prerequisites: Before beginning this tutorial, you should know how to: Use HTML, CSS, and JavaScript to build a web page. Use DevTools to make basic changes to CSS. Run a local HTTP web server.

Overview

Workspaces enable you to save a change that you make in Devtools to a local copy of the same file on your computer. For example, suppose: You have the source code for your site on your desktop. You're running a local web server from the source code directory, so that the site is accessible at localhost:8080. You've got localhost:8080 open in Google Chrome, and you're using DevTools to change the site's CSS. With Workspaces enabled, the CSS changes that you make within DevTools are saved to the source code on your desktop.

Limitations

If you're using a modern framework, it probably transforms your source code from a format that's easy for you to maintain into a format that's optimized to run as quickly as possible. Workspaces is usually able to map the optimized code back to your original source code with the help of source maps. But there's a lot of variation between frameworks over how they use source maps. Devtools simply can't support all the variations. Workspaces is known to not work with these frameworks: Create React App If you run into issues while using Workspaces with your framework of choice, or you get it working after some custom configuration, please start a thread in the mailing list or ask a question on Stack Overflow to share your knowledge with the rest of the DevTools community.

Related feature: Local Overrides

Local Overrides is another DevTools feature that is similar to Workspaces. Use Local Overrides when you want to experiment with changes to a page, and you need to see those changes across page loads, but you don't care about mapping your changes to the page's source code.

Step 1: Setup

Complete this tutorial to get hands-on experience with Workspaces.

 Set up the demo

Open the demo. In the bottom-left of the editor, click the button labelled Tools. Under Tools, select Import/Export > Download Project. Close the tab. Unzip the source code and move the unzipped app directory to your desktop. For the rest of this tutorial this directory will be referred to as ~/Desktop/app. Start a local web server in ~/Desktop/app. Below is some sample code for starting up SimpleHTTPServer, but you can use whatever server you prefer. cd ~/Desktop/app
# If your Python version is 3.X
# On Windows, try "python -m http.server" or "py -3 -m http.server"
python3 -m http.server
# If your Python version is 2.X
python -m SimpleHTTPServer
Open a tab in Google Chrome and go to locally-hosted version of the site. You should be able to access it via a URL like localhost:8080. The exact port number may be different. Figure 1. The demo

 Set up DevTools

Press Command+Option+J (Mac) or Control+Shift+J (Windows, Linux, Chrome OS) to open the Console panel of DevTools. Figure 2. The Console panel Click the Sources tab. Click the Filesystem tab. Figure 3. The Filesystem tab Click Add Folder To Workspace. Select ~/Desktop/app. Click Allow to give DevTools permission to read and write to the directory. In the Filesystem tab, there is now a green dot next to index.html, script.js, and styles.css. These green dots mean that DevTools has established a mapping between the network resources of the page, and the files in ~/Desktop/app. Figure 4. The Filesystem tab now shows a mapping between the local files and the network ones

Step 2: Save a CSS change to disk

Open ~/Desktop/app/styles.css in a text editor. Notice how the color property of h1 elements is set to fuchsia. Figure 5. Viewing styles.css in a text editor Close the text editor. Back in DevTools, click the Elements tab. Change the value of the color property of the <h1> element to your favorite color. Remember that you need to click the <h1> element in the DOM Tree in order to see the CSS rules applied to it in the Styles pane. The green dot next to styles.css:1 means that any change you make will get mapped to ~/Desktop/app/styles.css. Figure 6. Setting the color property of the h1 element to green Open ~/Desktop/app/styles.css in a text editor again. The color property is now set to your favorite color. Reload the page. The color of the <h1> element is still set to your favorite color. This works because when you made the change, DevTools saved the change to disk. And then, when you reloaded the page, your local server served the modified copy of the file from disk.

Step 3: Save an HTML change to disk

 Try changing HTML from the Elements panel

Warning Warning: The workflow that you're about to try doesn't work. You're trying it now so that you don't waste time later trying to figure out why it's not working. Click the Elements tab. Double click the text content of the h1 element, which says Workspaces Demo, and replace it with I Cake. Figure 7. Attempting to change HTML from the DOM Tree of the Elements panel Open ~/Desktop/app/index.html in a text editor. The change that you just made isn't there. Reload the page. The page reverts to its original title.

Optional: Why it doesn't work

Note: This section describes why the workflow from Try changing HTML from the Elements panel doesn't work. You can skip this section if you don't care why. The tree of nodes that you see on the Elements panel represents the page's DOM. To display a page, a browser fetches HTML over the network, parses the HTML, and then converts it into a tree of DOM nodes. If the page has any JavaScript, that JavaScript may add, delete, or change DOM nodes. CSS can change the DOM, too, via the content property. The browser eventually uses the DOM to determine what content it should present to browser users. Therefore, the final state of the page that users see may be very different from the HTML that the browser fetched. This makes it difficult for DevTools to resolve where a change made in the Elements panel should be saved, because the DOM is affected by HTML, JavaScript, and CSS. In short, the DOM Tree !== HTML.

 Change HTML from the Sources panel

If you want to save a change to the page's HTML, do it via the Sources panel. Click the Sources tab. Click the Page tab. Click (index). The HTML for the page opens. Replace <h1>Workspaces Demo</h1> with <h1>I Cake</h1>. See Figure 11. Press Command+S (Mac) or Control+S (Windows, Linux, Chrome OS) to save the change. Reload the page. The <h1> element is still displaying the new text. Figure 8. Line 12 has been set to I Cake Open ~/Desktop/app/index.html. The <h1> element contains the new text.

Step 4: Save a JavaScript change to disk

The Sources panel is also the place to make changes to JavaScript. But sometimes you need to access other panels, such as the Elements panel or the Console panel, while making changes to your site. There's a way to have the Sources panel open alongside other panels. Click the Elements tab. Press Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux, Chrome OS). The Command Menu opens. Type QS, then select Show Quick Source. At the bottom of your DevTools window there is now a Quick Source tab. The tab is displaying the contents of index.html, which is the last file you edited in the Sources panel. The Quick Source tab gives you the editor from the Sources panel, so that you can edit files while having other panels open. Figure 9. Opening the Quick Source tab via the Command Menu Press Command+P (Mac) or Control+P (Windows, Linux, Chrome OS) to open the Open File dialog. See Figure 10. Type script, then select app/script.js. Figure 10. Opening script.js via the Open File dialog Notice the Save Changes To Disk With Workspaces link in the demo. It's styled regularly. Add the following code to the bottom of script.js via the Quick Source tab. console.log('greetings from script.js'); document.querySelector('a').style = 'font-style:italic'; Press Command+S (Mac) or Control+S (Windows, Linux, Chrome OS) to save the change. Reload the page. The link on the page is now italic. Figure 11. The link on the page is now italic

Next steps

Congratulations, you have completed the tutorial. Improve article


Debug Progressive Web Apps

Use the Application panel to inspect, modify, and debug web app manifests, service workers, and service worker caches. Related Guides: Progressive Web Apps This guide only discusses the Progressive Web App features of the Application panel. If you're looking for help on the other panes, check out the last section of this guide, Other Application panel guides.

Summary

Use the Manifest pane to inspect your web app manifest and trigger Add to Homescreen events. Use the Service Workers pane for a whole range of service-worker-related tasks, like unregistering or updating a service, emulating push events, going offline, or stopping a service worker. View your service worker cache from the Cache Storage pane. Unregister a service worker and clear all storage and caches with a single button click from the Clear storage pane.

Web app manifest

If you want your users to be able to add your app to their mobile homescreens, you need a web app manifest. The manifest defines how the app appears on the homescreen, where to direct the user when launching from homescreen, and what the app looks like on launch. Related Guides: Improve user experiences with a Web App Manifest Using App Install Banners Once you've got your manifest set up, you can use the Manifest pane of the Application panel to inspect it. To look at the manifest source, click the link below App Manifest label (https://airhorner.com/manifest.json in the screenshot above). Press the Add to homescreen button to simulate an Add to Homescreen event. Check out the next section for more information. The Identity and Presentation sections just display fields from the manifest source in a more user-friendly display. The Icons section displays every icon that you've specified.

 Simulate Add to Homescreen events

A web app can only be added to a homescreen when the site is visited at least twice, with at least five minutes between visits. While developing or debugging your Add to Homescreen workflow, this criteria can be inconvenient. The Add to homescreen button on the App Manifest pane lets you simulate Add to Homescreen events whenever you want. You can test out this feature with the Google I/O 2016 progressive web app, which has proper support for Add to Homescreen. Clicking on Add to Homescreen while the app is open prompts Chrome to display the "add this site to your shelf" banner, which is the desktop equivalent of the "add to homescreen" banner for mobile devices. Tip: Keep the Console drawer open while simulating Add to Homescreen events. The Console tells you if your manifest has any issues and logs other information about the Add to Homescreen lifecycle. The Add to Homescreen feature cannot yet simulate the workflow for mobile devices. Notice how the "add to shelf" prompt was triggered in the screenshot above, even though DevTools is in Device Mode. However, if you can successfully add your app to your desktop shelf, then it'll work for mobile, too. If you want to test out the genuine mobile experience, you can connect a real mobile device to DevTools via [remote debugging]remote debugging, and then click the Add to Homescreen button (on DevTools) to trigger the "add to homescreen" prompt on the connected mobile device.

Service workers

Service workers are a fundamental technology in the future web platform. They are scripts that the browser runs in the background, separate from a web page. These scripts enable you to access features that don't need a web page or user interaction, like push notifications, background sync, and offline experiences. Related Guides: Intro to Service Workers Push Notifications: Timely, Relevant, and Precise The Service Workers pane in the Application panel is the main place in DevTools to inspect and debug service workers. If a service worker is installed to the currently open page, then you'll see it listed on this pane. For example, in the screenshot above there's a service worker installed for the scope of https://events.google.com/io2016/. The Offline checkbox puts DevTools into offline mode. This is equivalent to the offline mode available from the Network panel, or the Go offline option in the Command Menu. The Update on reload checkbox forces the service worker to update on every page load. The Bypass for network checkbox bypasses the service worker and forces the browser to go to the network for requested resources. The Update button performs a one-time update of the specified service worker. The Push button emulates a push notification without a payload (also known as a tickle). The Sync button emulates a background sync event. The Unregister button unregisters the specified service worker. Check out Clear storage for a way to unregister a service worker and wipe storage and caches with a single button click. The Source line tells you when the currently running service worker was installed. The link is the name of the service worker's source file. Clicking on the link sends you to the service worker's source. The Status line tells you the status of the service worker. The number on this line (#1 in the screenshot above) indicates how many times the service worker has been updated. If you enable the update on reload checkbox you'll notice that the number increments on every page load. Next to the status you'll see a start button (if the service worker is stopped) or a stop button (if the service worker is running). Service workers are designed to be stopped and started by the browser at any time. Explicitly stopping your service worker using the stop button can simulate that. Stopping your service worker is a great way to test how your code behaves when the service worker starts back up again. It frequently reveals bugs due to faulty assumptions about persistent global state. The Clients line tells you the origin that the service worker is scoped to. The focus button is mostly useful when you've enabled the show all checkbox. When that checkbox is enabled, all registered service workers are listed. If you click on the focus button next to a service worker that is running in a different tab, Chrome focuses on that tab. If the service worker causes any errors, a new label called Errors shows up.

Service worker caches

The Cache Storage pane provides a read-only list of resources that have been cached using the (service worker) Cache API. Note that the first time you open a cache and add a resource to it, DevTools might not detect the change. Reload the page and you should see the cache. If you've got two or more caches open, you'll see them listed below the Cache Storage dropdown.

Quota usage

Some responses within the Cache Storage pane may be flagged as being "opaque". This refers to a response retrieved from a different origin, like from a CDN or remote API, when CORS is not enabled. In order to avoid leakage of cross-domain information, there's significant padding added to the size of an opaque response used for calculating storage quota limits (i.e. whether a QuotaExceeded exception is thrown) and reported by the navigator.storage API. The details of this padding vary from browser to browser, but for Google Chrome, this means that the minimum size that any single cached opaque response contributes to the overall storage usage is approximately 7 megabytes. You should keep this in mind when determining how many opaque responses you want to cache, since you could easily exceeded storage quota limitations much sooner than you'd otherwise expect based on the actual size of the opaque resources. Related Guides: Stack Overflow: What limitations apply to opaque responses? Workbox: Understanding Storage Quota

Clear storage

The Clear Storage pane is a very useful feature when developing progressive web apps. This pane lets you unregister service workers and clear all caches and storage with a single button click. Check out the section below to learn more. Related Guides: Clear Storage

Other Application panel guides

Check out the guides below for more help on the other panes of the Application panel. Related Guides: Inspect page resources Inspect and manage local storage and caches Improve article


Understand security issues

Use the Security Panel in Chrome DevTools to make sure HTTPS is properly implemented on a page. See Why HTTPS Matters to learn why every website should be protected with HTTPS, even sites that don't handle sensitive user data.

Open the Security panel

The Security panel is the main place in DevTools for inspecting the security of a page. Open DevTools. Click the Security tab to open the Security panel. Figure 1. The Security panel

Common problems

 Non-secure main origins

When the main origin of a page is not secure, the Security Overview says This page is not secure. Figure 2. A non-secure page This problem occurs when the URL that you visited was requested over HTTP. To make it secure you need to request it over HTTPS. For example, if you look at the URL in your address bar, it probably looks similar to http://example.com. To make it secure the URL should be https://example.com. If you've already got HTTPS set up on your server, all you need to do to fix this problem is configure your server to redirect all HTTP requests to HTTPS. If you don't have HTTPS set up on your server, Let's Encrypt provides a free and relatively-easy way to start the process. Or, you might consider hosting your site on a CDN. Most major CDNs host sites on HTTPS by default now. Tip The Redirect HTTP Traffic To HTTPS audit in Lighthouse can help automate the process of making sure that all HTTP requests are redirected to HTTPS.

 Mixed content

Mixed content means that the main origin of a page is secure, but the page requested resources from non-secure origins. Mixed content pages are only partially protected because the HTTP content is accessible to sniffers and vulnerable to man-in-the-middle attacks. Figure 3. Mixed content In Figure 3 above, clicking View 1 request in Network panel opens the Network panel and applies the mixed-content:displayed filter so that the Network Log only shows non-secure resources. Figure 4. Mixed resources in the Network Log

View details

 View main origin certificate

From the Security Overview click View certificate to quickly inspect the main origin's certificate. Figure 5. A main origin certificate

 View origin details

Click one of the entries in the left-hand nav to view the origin's details. From the details page you can view connection and certificate information. Certificate transparency information is also shown when available. Figure 6. Main origin details Improve article


Keyboard shortcuts

This page is a reference of keyboard shortcuts in Chrome DevTools. You can also find shortcuts in tooltips. Hover over a UI element of DevTools to display its tooltip. If the element has a shortcut, the tooltip includes it.

Keyboard shortcuts for opening DevTools

To open DevTools, press the following keyboard shortcuts while your cursor is focused on the browser viewport:
Action Mac Windows / Linux
Open whatever panel you used last Command+Option+I F12 or Control+Shift+I
Open the Console panel Command+Option+J Control+Shift+J
Open the Elements panel Command+Shift+C or Command+Option+C Control+Shift+C

Global keyboard shortcuts

The following keyboard shortcuts are available in most, if not all, DevTools panels.
Action Mac Windows / Linux
Show Settings ? or Function+F1 ? or F1
Focus the next panel Command+] Control+]
Focus the previous panel Command+[ Control+[
Switch back to whatever docking position you last used. If DevTools has been in its default position for the entire session, then this shortcut undocks DevTools into a separate window Command+Shift+D Control+Shift+D
Toggle Device Mode Command+Shift+M Control+Shift+M
Toggle Inspect Element Mode Command+Shift+C Control+Shift+C
Open the Command Menu Command+Shift+P Control+Shift+P
Toggle the Drawer EscapeEscape
Normal reload Command+R F5 or Control+R
Hard reload Command+Shift+R Control+F5 or Control+Shift+R
Search for text within the current panel. Not supported in the Audits, Application, and Security panels Command+F Control+F
Opens the Search tab in the Drawer, which lets you search for text across all loaded resources Command+Option+F Control+Shift+F
Open a file in the Sources panel Command+O or Command+P Control+O or Control+P
Zoom in Command+Shift++ Control+Shift++
Zoom out Command+- Control+-
Restore default zoom level Command+0 Control+0
Run snippet Press Command+O to open the Command Menu, type ! followed by the name of the script, then press Enter Press Control+O to open the Command Menu, type ! followed by the name of the script, then press Enter

Elements panel keyboard shortcuts

Action Mac Windows / Linux
Undo changeCommand+Z Control+Z
Redo changeCommand+Shift+Z Control+Y
Select the element above / below the currently-selected elementUp Arrow / Down Arrow Up Arrow / Down Arrow
Expand the currently-selected node. If the node is already expanded, this shortcut selects the element below itRight Arrow Right Arrow
Collapse the currently-selected node. If the node is already collapsed, this shortcut selects the element above itLeft ArrowLeft Arrow
Expand or collapse the currently-selected node and all of its children Hold Option then click the arrow icon next to the element's nameHold Control+Alt then click the arrow icon next to the element's name
Toggle Edit Attributes mode on the currently-selected elementEnter Enter
Select the next / previous attribute after entering Edit Attributes mode Tab / Shift+Tab Tab / Shift+Tab
Hide the currently-selected elementHH
Toggle Edit as HTML mode on the currently-selected element Function+F2 F2

 Styles pane keyboard shortcuts

Action Mac Windows / Linux
Go to the line where a property value is declaredHold Command then click the property value Hold Control then click the property value
Cycle through the RBGA, HSLA, and Hex representations of a color valueHold Shift then click the Color Preview box next to the valueHold Shift then click the Color Preview box next to the value
Select the next / previous property or value Click a property name or value then press Tab / Shift+Tab Click a property name or value then press Tab / Shift+Tab
Increment / decrement a property value by 0.1Click a value then press Option+Up Arrow / Option+Down Arrow Click a value then press Alt+Up Arrow / Alt+Down Arrow
Increment / decrement a property value by 1Click a value then press Up Arrow / Down Arrow Click a value then press Up Arrow / Down Arrow
Increment / decrement a property value by 10 Click a value then press Shift+Up Arrow / Shift+Down Arrow Click a value then press Shift+Up Arrow / Shift+Down Arrow
Increment / decrement a property value by 100Click a value then press Command+Up Arrow / Command+Down Arrow Click a value then press Control+Up Arrow / Control+Down Arrow
Cycle through the degrees (deg), gradians (grad), radians (rad) and turns (turn) representations of an angle valueHold Shift then click the Angle Preview box next to the value Hold Shift then click the Angle Preview box next to the value
Increment / decrement an angle value by 1Click the Angle Preview box next to the value then press Up Arrow / Down Arrow Click the Angle Preview box next to the value then press Up Arrow / Down Arrow
Increment / decrement an angle value by 10Click the Angle Preview box next to the value then press Shift+Up Arrow / Shift+Down Arrow Click the Angle Preview box next to the value then press Shift+Up Arrow / Shift+Down Arrow
Increment / decrement an angle value by 15 Click the Angle Preview box next to the value then press Shift, click / mouse slide on the Angle Clock Overlay Click the Angle Preview box next to the value then press Shift, click / mouse slide on the Angle Clock Overlay

Sources panel keyboard shortcuts

Action Mac Windows / Linux
Pause script execution (if currently running) or resume (if currently paused)F8 or Command+\ F8 or Control+\
Step over next function callF10 or Command+' F10 or Control+'
Step into next function callF11 or Command+; F11 or Control+;
Step out of current functionShift+F11 or Command+Shift+; Shift+F11 or Control+Shift+;
Continue to a certain line of code while pausedHold Command and then click the line of code Hold Control and then click the line of code
Select the call frame below / above the currently-selected frame Control+. / Control+, Control+. / Control+,
Save changes to local modifications Command+S Control+S
Save all changes Command+Option+S Control+Alt+S
Go to line Control+G Control+G
Jump to a line number of the currently-open filePress Command+O to open the Command Menu, type : followed by the line number, then press Enter Press Control+O to open the Command Menu, type : followed the line number, then press Enter
Jump to a column of the currently-open file (for example line 5, column 9)Press Command+O to open the Command Menu, type :, then the line number, then another :, then the column number, then press Enter Press Control+O to open the Command Menu, type :, then the line number, then another :, then the column number, then press Enter
Go to a function declaration (if currently-open file is HTML or a script), or a rule set (if currently-open file is a stylesheet) Press Command+Shift+O, then type in the name of the declaration / rule set, or select it from the list of optionsPress Control+Shift+O, then type in the name of the declaration / rule set, or select it from the list of options
Close the active tabOption+W Alt+W

 Code Editor keyboard shortcuts

Action Mac Windows / Linux
Delete all characters in the last word, up to the cursor Option+Delete Control+Delete
Add or remove a line-of-code breakpoint Focus your cursor on the line and then press Command+B Focus your cursor on the line and then press Control+B
Go to matching bracketControl+M Control+M
Toggle single-line comment. If multiple lines are selected, DevTools adds a comment to the start of each lineCommand+/ Control+/
Select / de-select the next occurrence of whatever word the cursor is on. Each occurrence is highlighted simultaneouslyCommand+D / Command+U Control+D / Control+U

Performance panel keyboard shortcuts

Action Mac Windows / Linux
Start / stop recording Command+E Control+E
Save recording Command+S Control+S
Load recording Command+O Control+O

Memory panel keyboard shortcuts

Action Mac Windows / Linux
Start / stop recording Command+E Control+E

Console panel keyboard shortcuts

Action Mac Windows / Linux
Accept autocomplete suggestion Right Arrow or Tab Right Arrow or Tab
Reject autocomplete suggestion EscapeEscape
Get previous statementUp Arrow Up Arrow
Get next statementDown ArrowDown Arrow
Focus the Console Control+` Control+`
Clear the Console Command+K or Option+L Control+L
Force a multi-line entry. Note that DevTools should detect multi-line scenarios by default, so this shortcut is now usually unnecessaryCommand+Return Shift+Enter
ExecuteReturn Enter
Expand all sub-properties of an object that's been logged to the ConsoleHold Alt then click Expand Hold Alt then click Expand
Improve article


View page resources

This guide teaches you how to use Chrome DevTools to view a web page's resources. Resources are the files that a page needs in order to display correctly. Examples of resources include CSS, JavaScript, and HTML files, as well as images. This guide assumes that you're familiar with the basics of web development and Chrome DevTools.

Open resources

When you know the name of the resource that you want to inspect, the Command Menu provides a fast way of opening the resource. Press Control+P or Command+P (Mac). The Open File dialog opens. Figure 1. The Open File dialog Select the file from the dropdown, or start typing the filename and press Enter once the correct file is highlighted in the autocomplete box. Figure 2. Typing a filename in the Open File dialog

 Open resources in the Network panel

See Inspect a resource's details. Figure 3. Inspecting a resource in the Network panel

 Reveal resources in the Network panel from other panels

The Browse resources section below shows you how to view resources from various parts of the DevTools UI. If you ever want to inspect a resource in the Network panel, right-click the resource and select Reveal in Network panel. Figure 4. The Reveal in Network panel option

Browse resources

 Browse resources in the Network panel

See Log network activity. Figure 5. Page resources in the Network Log

 Browse by directory

To view a page's resources organized by directory: Click the Sources tab to open the Sources panel. Click the Page tab to show the page's resources. The Page pane opens. Figure 6. The Page pane Here's a breakdown of the non-obvious items in Figure 6: top is the main document browsing context. airhorner.com represents a domain. All resources nested under it come from that domain. For example, the full URL of the comlink.global.js file is probably https://airhorner.com/scripts/comlink.global.js. scripts is a directory. (index) is the main HTML document. iu3 is another browsing context. This context was probably created by an <iframe> element embedded in the main document HTML. sw.js is a service worker execution context. Click a resource to view it in the Editor. Figure 7. Viewing a file in the Editor

 Browse by filename

By default the Page pane groups resources by directory. To disable this grouping and view each domain's resources as a flat list: Open the Page pane. See Browse by directory. Click More Options and disable Group By Folder. Figure 8. The Group By Folder option Resources are organized by file type. Within each file type the resources are organized alphabetically. Figure 9. The Page pane after disabling Group By Folder

 Browse by file type

To group resources together based on their file type: Click the Application tab. The Application panel opens. By default the Manifest pane usually opens first. Figure 10. The Application panel Scroll down to the Frames pane. Figure 11. The Frames pane Expand the sections that you're interested in. Click a resource to view it. Figure 11. Viewing a resource in the Application panel

Browse files by type in the Network panel

See Filter by resource type. Figure 12. Filtering for CSS in the Network Log Improve article


Customization

This page lists the ways you can customize Chrome DevTools.

Settings

Settings > Preferences contains many options for customizing DevTools. To open Settings, do one of the following: Press F1 while DevTools is in focus. Click Settings. Figure 1. Settings.

Drawer

The Drawer contains many hidden features. Press Escape to open or close the Drawer. Figure 2. The Drawer. Click More to open other Drawer tabs. Figure 3: The button for opening Drawer tabs, outlined in blue.

Reorder panels

Click and drag a panel tab to change its ordering. Your custom tab order persists across DevTools sessions. Figure 4: A DevTools window with a custom tab ordering. By default, the Network panel tab is usually the fourth from the left. In the screenshot, it's the first from the left.

Change DevTools placement

See Chrome DevTools Placement. Figure 5. Undocked DevTools.

Dark theme

See Enable Dark Theme. Figure 6. The dark theme.

Experiments

To enable DevTools experiments: Go to chrome://flags/#enable-devtools-experiments. Click Enable. Click Relaunch Now, at the bottom of the page. The next time you open DevTools, there's a new page called Experiments in Settings. Improve article


Enable dark theme

You can enable dark theme in Settings or the Command Menu.

Set up dark theme from Settings

Click Settings . You can also open Settings by pressing F1. Under Preferences > Appearance > Theme select Dark.

Set up dark theme from the Command Menu

Open the Command Menu. Start typing dark, select the Switch To Dark Theme command, and then press Enter to run the command. Improve article


Change placement: undock, dock to bottom, dock to left

By default DevTools is docked to the right of your viewport. You can also dock to bottom, dock to left, or undock to a DevTools to a separate bottom. Figure 1. Dock To Left. Figure 2. Dock To Bottom. Figure 3. Undocked.

Change placement from the main menu

Click Customize And Control DevTools . Figure 4. Selecting Undock Into Separate Window.

Change placement from the Command Menu

Open the Command Menu. Run one of the following commands: Dock to left, Dock to right, Dock to bottom, Undock into separate window or Restore last dock position. To toggle Restore last dock position with a keyboard shortcut, press Control+Shift+D (Linux/Windows) or Command+Shift+D (Mac). Figure 5. The undock command. Improve article