Use Playwright’s ordinary locators: they reach into supported Shadow DOM by default. Capture one matched component with locator.screenshot(), or capture the page with page.screenshot(). XPath does not pierce shadow roots, and Playwright’s documented locator behavior does not support closed-mode roots.
Capture a component inside Shadow DOM
Use an accessible role and name when the component exposes one; otherwise choose a stable locator that matches the page. Playwright’s locator methods work with elements in Shadow DOM by default. The example uses a button named “Details” only as a placeholder—replace it with a locator for your target.
As an Amazon Associate I earn from qualifying purchases.
import { test } from '@playwright/test';
test('capture a component rendered in Shadow DOM', async ({ page }) => {
await page.goto('https://example.com');
const component = page.getByRole('button', { name: 'Details' });
await component.screenshot({ path: 'details.png' });
});
Locator actions wait for their target according to Playwright’s locator behavior. If the component depends on additional asynchronous rendering, wait for the specific visible state you need before capturing it. Avoid selecting by implementation detail when a user-facing locator is available.
Playwright documents: “All locators in Playwright by default work with elements in Shadow DOM.” See Playwright’s Locators guide.
#1 Best Overall
Choose the screenshot scope
| What you need | Method | What it captures |
|---|---|---|
| One component | await locator.screenshot({ path: 'component.png' }) |
The matched element’s visible area, clipped to its size and position. |
| Current viewport | await page.screenshot({ path: 'page.png' }) |
The page as currently visible in the viewport. |
| Full scrollable page | await page.screenshot({ path: 'page.png', fullPage: true }) |
The full scrollable page. |
These are Playwright’s documented screenshot methods; see the Screenshots guide.
Understand selector and Shadow DOM limits
- Prefer role, text, or another user-facing locator where practical. These describe how a person recognizes the target and are often less tied to internal markup. See Other locators.
- CSS can pierce open shadow roots. It does not make closed-mode roots available.
- XPath does not pierce shadow roots. If an XPath locator cannot find the component, switch to a supported locator or CSS selector.
- Closed-mode shadow roots are unsupported by Playwright’s documented locator behavior. The ordinary locator approach cannot reach their internals.
See Locators and Other locators for the documented behavior.
Rank #2
Make component captures more predictable
Account for overlays and scrolling
A locator screenshot captures the matched element’s area, not an unobstructed reconstruction of it. A cookie banner, modal, or other overlay can cover the target. If the matched element is scrollable, the capture shows its current scroll position rather than automatically including all of its internal content. Move the element to the desired state and address covering overlays before taking the screenshot.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use screenshot styles to suppress changing UI
The screenshot API’s style option lets you apply CSS for a capture. Playwright documents that this stylesheet pierces Shadow DOM and inner frames, which can help hide or adjust dynamic elements for repeatable output. Check the Page API reference for the exact options supported by your installed Playwright version.
Keep visual-comparison runs consistent
If you are creating visual baselines, keep the browser and host conditions consistent. Playwright notes that screenshots can vary with operating system, browser version, settings, hardware, power source, and headless mode. See Visual comparisons.
Rank #3
Troubleshoot a missing or unexpected capture
| Symptom | Likely cause | What to try |
|---|---|---|
| Locator cannot find the internal element | The selector uses XPath, the target is in a closed-mode root, or the locator does not match the rendered page. | Try a role or text locator, or CSS for an open root. Confirm the target’s accessible name and state. |
| Screenshot shows a banner over the component | An overlay covers the matched element. | Dismiss or hide the overlay before capture, or use a screenshot style where appropriate. |
| Only part of a scrollable component appears | The locator screenshot captures the component’s current visible scroll position. | Scroll the component to the position you want before capturing it. |
| Visual output differs between runs or machines | Rendering conditions differ, or dynamic content changes. | Stabilize browser and host conditions, wait for the desired page state, and consider a screenshot style for changing UI. |
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. It can capture sites without setting up a Playwright browser; it is an alternative when you need a rendered page screenshot rather than direct access to a specific node inside a closed shadow root. Its capture flow accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot; each step can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, with the outcome indicated in response headers. An MCP server exposes screenshot tools to AI agents. Free includes 1,000 shots a month without a card; paid plans start at $5 for 3,000. See ScreenshotNeo and the API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
Sign up for 1,000 free screenshots a month, with no card required.
Recommended Free Tools
Quick Recap
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.

