How to Configure Accessibility Snapshots in Puppeteer
Learn how to capture and configure Puppeteer accessibility snapshots, scope the tree, include iframes, and interpret the result.
Use await page.accessibility.snapshot() to capture the current page’s accessibility tree in Puppeteer. Pass options to retain otherwise-pruned nodes, include iframe trees, or limit the snapshot to an element subtree. The result is a serialized accessibility node or null.
This guide covers Puppeteer’s snapshot configuration and a complete runnable example. A snapshot is useful for browser-side inspection, but it does not guarantee that every operating system or screen reader will announce the page in exactly the same way.
1. Install Puppeteer and capture a basic snapshot
Install Puppeteer in a Node.js project:
npm install puppeteer
Save this as snapshot.js and run it with node snapshot.js:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
const snapshot = await page.accessibility.snapshot();
console.dir(snapshot, { depth: null });
} finally {
await browser.close();
}
})();
The call reads the accessibility tree for the page in its current state. Navigate first, and perform any interactions or state changes that should be reflected in the snapshot before calling it.
2. Choose snapshot coverage and scope
The snapshot options control how much of the tree Puppeteer returns:
| Option | Default | Set it when |
|---|---|---|
interestingOnly |
true |
You need nodes that Puppeteer would otherwise prune from the tree. |
includeIframes |
false |
Relevant content is inside frames in the frame subtree. |
root |
Whole page | You only need the accessibility subtree for a particular element. |
Keep the default compact tree
const snapshot = await page.accessibility.snapshot();
With the default interestingOnly: true, Puppeteer filters out accessibility-tree nodes that are unused on most platforms and by most screen readers. This is often easier to inspect and process than the full Blink tree.
Include nodes Puppeteer normally prunes
const snapshot = await page.accessibility.snapshot({
interestingOnly: false,
});
Use false when investigating whether filtering explains a missing node or when you need the fuller Blink accessibility representation. The result may be larger and contain nodes that are not useful for the task you are debugging.
Include iframe accessibility trees
const snapshot = await page.accessibility.snapshot({
includeIframes: true,
});
Iframe inclusion is off by default. Enable it when the content you need to inspect is embedded in a frame. If the expected content remains absent, check that the frame has loaded and that it belongs to the page’s frame subtree.
Limit the snapshot to an element
The root option accepts an ElementHandle. Find the element first, then pass its handle:
const root = await page.$('main');
if (!root) {
throw new Error('Could not find the main element');
}
const snapshot = await page.accessibility.snapshot({ root });
console.dir(snapshot, { depth: null });
await root.dispose();
A scoped snapshot is useful when a page is large and you only need to inspect one region. Choose a selector that identifies the intended element; if it matches nothing, there is no handle to use as the root.
Combine the options
const snapshot = await page.accessibility.snapshot({
interestingOnly: false,
includeIframes: true,
root,
});
Use this combination when you need a fuller tree for a particular region, including iframe content. A subtree root does not change the meaning of the other options: they still determine filtering and iframe inclusion for the requested scope.
3. Inspect a control with an ARIA selector
A snapshot retrieves a serialized tree; it is not the same operation as finding or clicking an element. Puppeteer’s ::-p-aria(...) selector queries by computed accessible name and role. For example:
await page.locator('::-p-aria([name="Click me"][role="button"])').click();
Use an ARIA selector when you want to locate and interact with a control through its accessible name and role. Use snapshot() when you need to inspect the serialized accessibility tree. Puppeteer resolves ARIA relationships such as aria-labelledby before running the selector query.
4. Interpret the result carefully
The snapshot exposes Blink’s accessibility tree and approximates filtering for platform accessibility trees. Accessibility output is platform-specific, so the tree Puppeteer returns may differ from what a screen reader announces on a particular operating system.
- A node missing from the default snapshot may have been pruned. Retry with
interestingOnly: falseto investigate. - Content inside an iframe may be absent because
includeIframesdefaults tofalse. - A subtree result reflects the chosen root, rather than the entire page.
- A returned snapshot is not proof of a complete accessibility audit or identical output across assistive technologies.
5. Troubleshoot common problems
| Symptom | Likely cause | What to do |
|---|---|---|
snapshot is null |
The current page has no serialized root accessible node available. | Check that navigation completed and that the page is in the expected state, then call the method again. |
| A node is missing from the output | The default interestingOnly: true filter pruned it. |
Try interestingOnly: false to inspect the fuller tree. |
| Embedded content is missing | Iframe trees are excluded by default, or the frame content has not loaded. | Wait for the relevant content and use includeIframes: true. |
| Scoped snapshot fails or is empty | The root selector did not find the intended element, or the handle is no longer valid. | Check the selector, wait for the element if necessary, and pass a live ElementHandle. |
| Screen-reader output differs from the snapshot | Puppeteer exposes Blink’s tree, while platform accessibility behavior varies. | Use the snapshot for browser inspection and verify behavior with the target platform and assistive technology. |
| Snapshot does not reflect an interaction | The snapshot was taken before the page reached the desired state. | Perform the interaction and wait for the resulting content before capturing the tree. |
6. Performance, reliability, and cost
A whole-page snapshot can contain more information than a focused inspection needs. Keep the default filtering for a compact result, and use root to target a relevant subtree on large pages. Turning off filtering and including iframes can increase the amount of tree data to process.
For reliable results, capture after the relevant navigation, frame load, or interaction has completed. Handle the possibility of a null result, and dispose of element handles when finished. Puppeteer snapshot configuration itself does not imply a hosted service charge; the practical costs are the browser runtime and the work needed to process the returned tree.
7. Or skip the browser setup
If you need a visual page capture alongside browser-side accessibility work, ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF. See the ScreenshotNeo site and its API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
- Cookie and consent banners are accepted like a visitor, and 60+ known consent platforms, newsletter popups, and chat widgets are removed before the shot; each step can be turned off.
- Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Response headers say which page verdict was returned and whether it was billed.
- An MCP server gives AI agents tools for screenshots, page information, and PDF capture.
- The Free plan includes 1,000 screenshots a month with no card. Paid plans start at $5 for 3,000; every feature is on every plan.
Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.
8. FAQ
Does an accessibility snapshot test whether my site is accessible?
No. It is a view of the browser accessibility tree, not a complete accessibility audit or a guarantee of assistive technology behavior.
Can I use a snapshot to click a button?
The snapshot is for inspection. To locate and interact with a control, use a locator or an ARIA selector such as ::-p-aria(...).
When should I capture the snapshot?
Capture it after the page and any relevant dynamic content have reached the state you want to inspect.


