October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk4 min

How to Handle the Shadow DOM in Selenium

Locate the shadow host, retrieve its root with Selenium’s native API, and search inside that root. Includes Python, JavaScript, and Java examples plus troubleshooting.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To interact with an element inside a Shadow DOM using Selenium, first locate its shadow host in the regular document, retrieve the host’s shadow root with your language binding’s native API, then find the target element from that root. In Python, use host.shadow_root; JavaScript and Java use getShadowRoot(). You usually do not need JavaScript execution for this.

Find an element inside a shadow root with Python

The host is an ordinary element in the page, so locate it with the WebDriver as usual. The shadow root then becomes a separate search context: call find_element on that root to locate its descendants.

As an Amazon Associate I earn from qualifying purchases.

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

host = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.CSS_SELECTOR, "my-component"))
)
shadow_root = host.shadow_root
button = shadow_root.find_element(By.CSS_SELECTOR, "button.submit")
button.click()

This assumes driver has already been created and navigated to the page. The explicit wait checks that the host exists; it does not by itself guarantee that the component has finished attaching its shadow root. Selenium’s Python API also supports shadow_root.find_elements(...) when you need every matching descendant.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use the native API in JavaScript or Java

Binding syntax differs, so do not copy Python’s shadow_root property syntax into another language.

JavaScript

The JavaScript binding returns a promise from getShadowRoot(). Await it, then locate descendants from the returned root:

const host = await driver.findElement(By.css('my-component'));
const shadowRoot = await host.getShadowRoot();
const button = await shadowRoot.findElement(By.css('button.submit'));
await button.click();

This fragment assumes the Selenium JavaScript package, driver, and By are already set up. Add an appropriate wait if the host or component is rendered asynchronously.

Java

Java’s WebElement.getShadowRoot() returns a SearchContext; use that context for the inner lookup:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
WebElement host = driver.findElement(By.cssSelector("my-component"));
SearchContext shadowRoot = host.getShadowRoot();
WebElement button = shadowRoot.findElement(By.cssSelector("button.submit"));
button.click();

This fragment assumes driver is initialized and the Selenium WebDriver classes are imported. Java documents NoSuchShadowRootException for the case where the element has no shadow root.

Handle nested roots and dynamic components

Each shadow root is its own search context. For a component nested inside another component’s shadow tree, locate the inner host from the outer root, retrieve its root, and continue:

outer_host = driver.find_element(By.CSS_SELECTOR, "outer-component")
outer_root = outer_host.shadow_root
inner_host = outer_root.find_element(By.CSS_SELECTOR, "inner-component")
inner_root = inner_host.shadow_root
button = inner_root.find_element(By.CSS_SELECTOR, "button.submit")

Use the same sequence in other bindings with their corresponding getShadowRoot() API. If rendering is asynchronous, wait for the relevant host and component state before accessing the root or its descendants. A wait for the outer host alone cannot establish that a nested host or target control is ready.

Diagnose missing roots and stale references

  • No shadow root: Confirm that the located element is the actual shadow host, not a nearby wrapper or a descendant. Check that the component has attached its root before requesting it. In Java, this condition is documented as NoSuchShadowRootException.
  • Host not found: The host may not yet be present, may use a different selector, or may not have rendered on the current page. Verify the selector and wait for the host in the regular document context.
  • Target not found inside the root: Confirm the descendant selector and that the component has populated the root. Search using the returned shadow root rather than the top-level driver.
  • Detached or stale reference after rerender: A rerender can replace the host or detach its root. Discard the old host and root references, locate the host again, retrieve a fresh root, and repeat the descendant lookup. The WebDriver specification describes a shadow root as detached when its node document is no longer active or its host is stale.
  • Behavior differs by environment: Check the Selenium binding, browser, and driver versions in the failing test environment. Support is not guaranteed solely by meeting a browser-version threshold.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Check browser support and avoid unnecessary JavaScript workarounds

The Selenium Python WebElement reference documents shadow-root support from Chromium 96, Firefox 96, and Safari 16.4 onward. These are the thresholds stated in that Python reference, not a guarantee for every binding, browser build, driver, or deployment. Verify the versions in your own test matrix.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

WebDriver has dedicated protocol support for shadow-root references and commands, so prefer the native API when your binding and browser support it. JavaScript execution is not the default workaround. The W3C WebDriver specification cited for this behavior is a Working Draft dated 2026-05-28, not a finalized recommendation.

Or skip the browser setup

If your goal is a screenshot rather than interacting with a shadow-root element, ScreenshotNeo can return an image or PDF through a single GET request. It is not a replacement for Selenium when your test needs to inspect or click an element inside a shadow root.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for API options. Cookie banners, newsletter popups, and chat widgets are removed before capture; bot checks, blank pages, and failed loads are not billed. An MCP server gives AI agents screenshot, page-info, and PDF tools. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.

Sign up for ScreenshotNeo’s free plan.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.