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.
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.
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
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.
SlackImprove 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
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 colorFigure 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
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 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 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:
<!doctypehtml> <html> <head> <title>Hello, world!</title> </head> <body> <h1>Hello, world!</h1> <p>This is a hypertext document on the World Wide Web.</p> <scriptsrc="/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:
<!doctypehtml> <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 Expandstack 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.
functionadd(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.
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 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.
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.
Log level: Info
Prints a stack trace to the Console.
constfirst=()=>{second();}; constsecond=()=>{third();}; constthird=()=>{fourth();}; constfourth=()=>{ 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.
WarningWarning: 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.
functionsum(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:
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> ... <linkrel="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.
CautionCaution: 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.
CautionCaution: 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
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
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
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 ConsoleImprove 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
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
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
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
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 ConsoleImprove 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
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 problemsMixed contentCOEP 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
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
Mobile
Mobile
Circle
touch
Mobile (no touch)
Mobile
Normal
click
Desktop
Desktop
Normal
click
Desktop (touch)
Desktop
Circle
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 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 ModelImprove 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:
functionupdateLabel(){ 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 anyclick 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:
functiononClick(){
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.
CautionCaution: 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.
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.
functionsum(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(){ functionhey(){ console.log('hey'); } functionyo(){ 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:
functionupdateHeader(){ var day =newDate().getDay(); var name =getName();// A updateName(name);// D } functiongetName(){ 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:
functionupdateHeader(){ var day =newDate().getDay(); var name =getName();// A updateName(name); } functiongetName(){ 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:
functionupdateHeader(){ var day =newDate().getDay(); var name =getName(); updateName(name);// C } functiongetName(){ 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:
functionanimate(){ 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
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.
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 FetchBackground SyncNotificationsPush 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.
CautionCaution: 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.
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 PanelsLighthouse.
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
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.
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).
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.
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.
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 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 =[];
functiongrow(){ for(var i =0; i <10000; i++){ document.body.appendChild(document.createElement('div')); } x.push(newArray(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;
functioncreate(){ 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 =[];
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:
functioncreateLargeClosure(){ var largeStr =newArray(1000000).join('x');
varlC=function(){// this is NOT a named function return largeStr; };
return lC; }
Whilst this example does:
functioncreateLargeClosure(){ var largeStr =newArray(1000000).join('x');
varlC=functionlC(){// 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.
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
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
WarningWarning: 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 ManifestUsing 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 WorkersPush 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
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
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
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
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
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.
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
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