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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

To access an element inside a Shadow DOM with Selenium, first find the element that hosts the shadow tree, retrieve its shadow root, and search from that root. A normal driver.find_element call does not cross the shadow boundary automatically.

from selenium.webdriver.common.by import By

host = driver.find_element(By.CSS_SELECTOR, "my-widget")
root = host.shadow_root
button = root.find_element(By.CSS_SELECTOR, "button.submit")
button.click()

The same host-to-root traversal applies in every Selenium binding. For nested components, find the next shadow host from the current root, retrieve that host’s root, and continue one boundary at a time.

What Shadow DOM changes for Selenium

Shadow DOM is an encapsulated DOM tree hidden inside an element. The outer element is the shadow host; its internal tree is a separate search context. Selenium’s WebDriver, WebElement and ShadowRoot objects all support element finding, but a locator issued against the document searches the document context, not descendants hidden behind a shadow root.

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

Use Selenium 4 or later for the documented shadow-root methods. The Python API reference lists Chromium 96, Firefox 96 and Safari 16.4 as support starting points for its shadow_root property; verify the exact browser, driver and language-binding combination used by your project.

#1 Best Overall
Sale
Philips 24 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 241V8LB
  • CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
  • WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
  • A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents

Basic workflow

  1. Use the intended browsing context. Switch to the correct window, frame or tab before locating the host. If the component is inside an iframe, switch into that frame first.
  2. Wait for the host. Custom elements often appear before their internal content is initialized.
  3. Locate the host in its parent context. Start with driver for a document-level host, or with an existing WebElement or ShadowRoot for a nested host.
  4. Retrieve the root. In Python use host.shadow_root; Java uses getShadowRoot(); JavaScript uses await host.getShadowRoot(); .NET uses GetShadowRoot().
  5. Find descendants from that root. Apply a CSS selector or another strategy supported by the binding.
  6. Repeat for nested components. Each new shadow host requires another root lookup.

Python example

This complete example waits for a host, enters its root, and clicks a button. Replace the URL and selectors with those from your application.

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

URL = "https://example.com"
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 20)

try:
    driver.get(URL)
    host = wait.until(EC.presence_of_element_located(
        (By.CSS_SELECTOR, "my-widget")
    ))
    root = host.shadow_root
    button = root.find_element(By.CSS_SELECTOR, "button.submit")
    button.click()
finally:
    driver.quit()

Python’s ShadowRoot API documents ID, name, XPath, CSS selector, class name, tag name, link text and partial-link-text strategies. CSS selectors are usually the clearest choice for component internals, but use the strategies supported by your installed binding.

Waiting for shadow content

Waiting only for the host can be insufficient when a framework attaches the root or renders its children asynchronously. A small custom wait can reacquire the host and return the descendant when it exists:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from selenium.common.exceptions import NoSuchElementException, NoSuchShadowRootException

def shadow_button(driver):
    try:
        host = driver.find_element(By.CSS_SELECTOR, "my-widget")
        root = host.shadow_root
        return root.find_element(By.CSS_SELECTOR, "button.submit")
    except (NoSuchElementException, NoSuchShadowRootException):
        return False

button = WebDriverWait(driver, 20).until(shadow_button)
button.click()

Use the exception name exposed by your Selenium version. If the component rerenders, reacquire the host and root rather than retaining old references.

Rank #2
Philips 22 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 221V8LB
  • CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
  • SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors

Nested shadow roots

Suppose outer-shell contains inner-panel, and the target button is inside the inner panel. Search each level from its current context:

outer_host = driver.find_element(By.CSS_SELECTOR, "outer-shell")
outer_root = outer_host.shadow_root

inner_host = outer_root.find_element(By.CSS_SELECTOR, "inner-panel")
inner_root = inner_host.shadow_root

save = inner_root.find_element(By.CSS_SELECTOR, "button.save")
save.click()

For three or more levels, continue the same pattern. A selector such as outer-shell inner-panel button.save does not automatically pierce shadow boundaries.

Equivalent code in Java, JavaScript and .NET

Java

WebElement host = driver.findElement(By.cssSelector("my-widget"));
SearchContext root = host.getShadowRoot();
WebElement button = root.findElement(By.cssSelector("button.submit"));
button.click();

getShadowRoot() returns a SearchContext. Use that context to locate descendants, then call getShadowRoot() again when a descendant is itself a host.

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

JavaScript (selenium-webdriver)

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

The JavaScript API reports a NoSuchShadowRootError when the selected element has no attached root.

Rank #3
Sale
Dell 24 Monitor - SE2426H - 23.8-inch FHD (1920x1080) 144Hz 1ms Display, in-Plane Switching (IPS) Technology, AMD FreeSync™, TÜV 3-Star 2X HDMI, Tilt
  • Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
  • Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
  • Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
  • In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
  • Ultra-thin bezels: Maximize your viewing experience with thin bezels.

C# / .NET

IWebElement host = driver.FindElement(By.CssSelector("my-widget"));
ISearchContext root = host.GetShadowRoot();
IWebElement button = root.FindElement(By.CssSelector("button.submit"));
button.Click();

In .NET, the returned ISearchContext is the context for descendant searches.

Choosing reliable locators

  • Prefer stable attributes supplied for testing, such as data-testid, or documented component attributes.
  • Avoid selectors tied to generated class names, deep implementation details or changing visual structure.
  • Scope every locator to the correct parent root. A locator passed to a ShadowRoot searches only descendants of that root.
  • When a component rerenders, reacquire the host, root and target to avoid stale element references.

Selenium notes that nested lookups can issue multiple browser commands. In ordinary DOM cases, one CSS or XPath locator can sometimes be more efficient; that optimization does not remove the requirement to respect each shadow boundary.

Troubleshooting common failures

NoSuchShadowRoot, NoSuchShadowRootException or NoSuchShadowRootError

This means Selenium did not obtain a root from the selected element. Check these causes in order:

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.
  • Wrong element: you selected a descendant or wrapper instead of the actual host. Inspect the markup and confirm the custom element owns the shadow tree.
  • Initialization race: the host exists, but the component has not attached its root. Wait and retry.
  • Unsupported versions: confirm Selenium 4 or later and compatible browser and driver versions. The Python reference lists Chromium 96, Firefox 96 and Safari 16.4 as starting points for that binding.
  • Context error: switch to the correct iframe or window before finding the host.

NoSuchElementException inside a root

The root exists, but the descendant is not present under that root yet, the selector is incorrect, or the target is in another nested root. Wait for the component’s content, verify the selector in developer tools, and traverse any inner host separately.

Rank #4
Samsung 27" Essential S3 (S36GD) Series FHD 1800R Curved Computer Monitor
  • CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
  • SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
  • MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
  • KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
  • INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient

Stale element reference

Framework rerendering can invalidate a previously returned host or root. Locate the host again, retrieve a fresh root and then find the target. Do not cache shadow elements across a known rerender.

Element is present but not usable

Presence is not visibility or interactability. Wait for the relevant state, scroll the element into view when necessary, and check overlays inside the component. If a click handler depends on a later application state, wait for that state rather than adding an arbitrary long delay.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Frames, windows and timing

Shadow DOM and iframes are different boundaries. Selenium cannot search an iframe’s document until you call the appropriate frame-switching method. After switching, locate the shadow host from the frame’s document. When returning to the top-level page, switch back before searching there.

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

Likewise, a new tab or window requires switching to its handle first. A correct selector in the wrong browsing context produces the same apparent “element not found” symptom as a bad selector.

Best Value
Sale
Sceptre New 22-Inch Gaming Monitor, FHD 1080p, Up to 144Hz, HDMI, DisplayPort, Built-in Speakers, Machine Black (E225W-FW144 Series, 2026)
  • 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
  • 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
  • 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.

Debugging checklist

  • Confirm the URL, active window and frame.
  • Inspect the live DOM and identify the exact shadow host.
  • Check whether the root is open and attached at the time of the lookup.
  • Log the Selenium, browser, driver and binding versions.
  • Wait for component initialization and target rendering.
  • Use a stable selector scoped to the current root.
  • Reacquire references after rerenders.

Or skip the browser setup

If your goal is a clean page image rather than interactive element automation, ScreenshotNeo provides a website screenshot API. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers. Its MCP server includes take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.

Here is the one-call cURL form (see the ScreenshotNeo documentation for all options):

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

It also supports full-page and element captures, device presets, retina scale, dark mode, PDF output, HTML/CSS rendering, custom JavaScript and CSS, clicks, waits, request blocking, headers, cookies, user agents, timezone and geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous webhooks and bulk capture of up to 100 URLs per call.

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

The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan. Sign up free for ScreenshotNeo.

Performance, reliability and cost considerations

Shadow-root traversal adds a lookup at each component boundary, so deeply nested designs can require several browser commands. Keep selectors stable, wait for meaningful readiness conditions and avoid unnecessary repeated searches. For tests, reuse a driver session where appropriate but reacquire elements after navigation or rerendering. Selenium itself does not report a universal success rate or performance benefit for one locator strategy; measure your own suite under its browser and application versions.

Frequently Asked Questions

Can Selenium access a closed shadow root?

The documented workflow requires Selenium to obtain a shadow-root search context from the host. If the component does not expose an accessible root, ordinary WebDriver shadow-root methods cannot search its internal tree; use an application-supported test hook or another interface instead.

Do I need JavaScript to enter a shadow root?

No. Selenium 4 provides native shadow-root methods in Python, Java, JavaScript and .NET. JavaScript execution is not required for the standard host-to-root workflow.

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

What should I update first when shadow-root lookups fail?

Verify the selected host and component lifecycle first, then confirm Selenium 4 or later and compatible browser and driver versions. A missing root is not automatically a Selenium defect.

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.