We use cookies to analyze site traffic and show personalized ads. You can accept all cookies or decline personalized advertising.
Learn more in our Privacy Policy.
How to reach elements hidden inside web components using Selenium 4's getShadowRoot().
Modern web apps often use Web Components that hide their internal HTML and CSS inside a Shadow DOM. This makes components reusable and encapsulated — but it also means normal Selenium locators can't see inside them directly.
<div id="shadow-host">).#shadow-root (open)).Before Selenium 4, dealing with Shadow DOM often required workarounds (JavaScript, etc.). Selenium 4 added a direct API: getShadowRoot() is called on a WebElement that is the shadow host. It returns a SearchContext, which you can use like driver to call findElement.
Use getShadowRoot() when:
#shadow-root in DevTools while inspecting an element.driver.findElement(By.id("shadow-btn")) fail, even though you see the element in DevTools.getShadowRoot() works only with open shadow roots (mode: 'open'). Closed shadow roots are not accessible through standard WebDriver.In this lab, you interact with a UI element that lives entirely inside a Shadow DOM.
The button above is inside a Shadow DOM. Try clicking it directly, then use Selenium to interact with it!
id="shadow-host"class="shadow-card"id="shadow-btn"driver.findElement(By.id("shadow-btn")). Selenium must:id="shadow-host" in the normal DOM.id="shadow-btn".12345678WebElement shadowHost = driver.findElement(By.id("shadow-host"));
SearchContext shadowRoot = shadowHost.getShadowRoot();
WebElement shadowButton = shadowRoot.findElement(By.id("shadow-btn"));
shadowButton.click();
driver.quit();id="shadow-host".getShadowRoot() on the host. This crosses the boundary into the shadow DOM and gives you a SearchContext for the shadow root.driver) to find the internal button with id="shadow-btn". A global driver.findElement(By.id("shadow-btn")) would fail because the button is hidden inside the shadow tree.WebElement.Always inspect for #shadow-root in DevTools. If you see it, you know you must use getShadowRoot() to reach inner elements.
Think of each shadow root as its own mini-page. Once you have SearchContext shadowRoot, treat it just like driver for that component.
Remember: getShadowRoot() works only for open shadow roots. For closed ones, Selenium cannot access elements by standard APIs — your tests might need to verify behavior indirectly.