Chrome DevTools Protocol (CDP) clients can now, according to a May 20, 2026 report from Nick Sweeting, read browser tab-strip metadata instead of guessing which tab is in front. The reported design adds an embedderData object to Target.TargetInfo; Chrome’s tab targets expose fields for tab-strip position, foreground state, pinning and optional tab-group membership. The implementation was reported in Chrome Canary 150.0.7848.0, not verified here as a current stable-channel feature.
What the reported CDP addition solves
Page automation normally tells you about a page, not the browser chrome surrounding it. Historically, a CDP client could not directly ask “What order are the tabs in?” or “Which tab is foregrounded?” It also lacked a reliable protocol-level answer for whether a tab was pinned, belonged to a tab group, or sat in a particular browser window. Nick Sweeting describes common workarounds such as assuming the newest tab is active, relying on target-list order, activating a target and observing the result, or injecting JavaScript into pages. Those methods can make incorrect assumptions, steal focus, or miss browser-UI changes that do not generate page JavaScript events.
The reported design supplies browser-owned state while preserving the distinction between browser containers and debuggable pages. It is therefore useful to automation clients that need an inventory of the tab strip, not merely a list of renderer targets.
Tab targets and page targets are different objects
Tab targets represent browser UI containers
A target with type equal to tab represents the browser’s tab container. Its metadata can describe where that tab appears in the strip and whether it is active, pinned or grouped. This is the layer that page-level JavaScript cannot reliably inspect.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
Page targets represent debugging surfaces
A page target represents a renderer or main-frame debugging surface. CDP domains such as Runtime.*, Page.* and DOM.* operate on this layer. One tab may be associated with multiple page-like targets, so a data model that assumes exactly one page target per tab can lose information.
Why the distinction matters
Use the tab target as the identity for browser-UI state and associate its page targets for page operations. Do not infer tab order from the order in which page targets happen to be returned. Sweeting’s account specifically warns that one tab can have several associated page targets.
What embedderData contains
The review described Chromium reviewers preferring an extensible embedderData object on Target.TargetInfo rather than a narrowly scoped Target.queryTabs command modeled on chrome.tabs.query(...). The embedder—Chrome in this case—can provide metadata appropriate to its own tab model.
| Field | Meaning | Availability described in the report |
|---|---|---|
tabStripIndex |
Position of the tab in the tab strip, suitable for sorting. | Shown for Chrome tab targets. |
tabActive |
Whether the tab is the foreground/active tab. | Shown for Chrome tab targets. |
tabPinned |
Whether the tab is pinned. | Shown for Chrome tab targets. |
tabGroupId |
Optional identifier for tab-group membership. | May be present when the tab is grouped. |
browserContextId |
Browser context identifier already present on TargetInfo. |
Existing field, not part of the new tab fields. |
windowId |
Containing browser window. | Obtained separately with Browser.getWindowForTarget when available. |
These names and semantics describe the implementation account, not a promise that every Chromium embedder or future Chrome version will expose identical fields.
Collection flow: enumerate tabs, attach related pages and resolve windows
- Call
Target.getTargets. Read the returnedtargetInfosand retain entries whosetypeistab. - Read
embedderData. ExtracttabStripIndex,tabActive,tabPinnedand, when present,tabGroupId. - Sort by
tabStripIndex. This gives the tab-strip order described by the browser rather than protocol-list order. - Call
Target.autoAttachRelated. Use the tab target to collect associated page targets. Keep a one-to-many relationship because a tab can have multiple page-like targets. - Resolve the browser window. For targets where the method is available, call
Browser.getWindowForTargetand store the returned window information alongside the tab record.
A practical record might contain the tab target ID, URL and title from TargetInfo, the embedder fields, a window identifier, and an array of related page target IDs. Treat missing optional fields as unknown rather than false.
Rank #2
Example CDP client logic
The following JavaScript illustrates the protocol sequence. It assumes an already-established CDP transport whose send function sends a method and parameters and returns the decoded result.
async function collectTabs(cdp) {
const { targetInfos } = await cdp.send('Target.getTargets');
const tabs = targetInfos
.filter(info => info.type === 'tab')
.sort((a, b) => (a.embedderData?.tabStripIndex ?? Infinity) -
(b.embedderData?.tabStripIndex ?? Infinity));
const result = [];
for (const tab of tabs) {
let windowInfo = null;
try {
windowInfo = await cdp.send('Browser.getWindowForTarget', {
targetId: tab.targetId
});
} catch (error) {
// The target may not be addressable by this command in the current setup.
}
let related = [];
try {
const attached = await cdp.send('Target.autoAttachRelated', {
targetId: tab.targetId,
waitForDebuggerOnStart: false,
flatten: true
});
related = attached?.targetInfos ?? attached?.targets ?? [];
} catch (error) {
// Keep the tab record even when related-target attachment is unavailable.
}
result.push({
targetId: tab.targetId,
url: tab.url,
title: tab.title,
embedderData: tab.embedderData ?? {},
window: windowInfo,
relatedPageTargets: related
});
}
return result;
}
Protocol response shapes can vary with the exact CDP revision and transport wrapper. Validate the returned object in your client, log unknown fields, and avoid treating an absent tabGroupId as proof that grouping is unsupported.
Pull-based updates, not a live tab event stream
The reported implementation is pull-based. Changes to embedderData do not emit new Target.targetInfoChanged events. To obtain current foreground state or order, call Target.getTargets again, or use Target.getTargetInfo for a known target. Sweeting mentions a dedicated state-change event and a single-call tab/page/window inventory as possible future improvements; those are not described as implemented.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallFor a responsive controller, choose a polling interval appropriate to your workload, refresh after operations that can change tabs, and tolerate a short interval in which cached state is stale. Do not build correctness around an event that the reported design does not provide.
Compatibility: what is actually established
Nick Sweeting reported the patch in Chrome Canary 150.0.7848.0, commit 5aa804ae0b62bd1b0d54f57494211239e2ed5ffe, on May 20, 2026. The report is available from Browserbase and the Browserbase Developer Blog. Those pages do not verify present-day stable-channel availability. Test the exact Chrome/Chromium build and CDP endpoint you deploy before depending on the fields.
The source names Playwright, Puppeteer, Selenium and Stagehand as examples of clients facing the historical problem. That is not a current support matrix: do not assume every version of those libraries exposes these fields. You may need a raw CDP session or a library escape hatch to read the target information.
Choosing an approach for tab state
| Approach | Browser-UI visibility | Focus risk | Dependence on page events | Typical weakness |
|---|---|---|---|---|
Reported embedderData |
Directly represents tab metadata when exposed. | None merely to read state. | None. | Build and endpoint compatibility must be verified. |
| Assume newest tab is foreground | Indirect guess. | None. | None. | Ordering and user actions can invalidate the assumption. |
| Activate a target and observe | Only by changing state. | Can steal focus. | Often requires observation logic. | Destructive for users and fragile under concurrency. |
| Use target-list order | Not guaranteed to be tab-strip order. | None. | None. | Protocol enumeration order is not UI order. |
| Inject page JavaScript | Cannot reliably see browser chrome. | None. | High. | Browser-UI changes may not trigger page events. |
These are trade-offs described by the contributor, not independent benchmark results.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Failure modes and fixes
No entries have type: "tab"
Cause: the connected browser, endpoint or CDP revision does not expose the reported embedder data. Fix: record the browser version and protocol version, test a Canary build containing the reported patch, and keep a fallback that treats tab metadata as unavailable.
embedderData is missing or incomplete
Cause: fields are embedder-provided and some are optional. Fix: use null-safe reads, distinguish “unknown” from false, and do not require tabGroupId for ungrouped-tab logic.
Window lookup fails
Cause: Browser.getWindowForTarget may not be available or may reject a target in the current connection mode. Fix: retain the tab record with a null window value and retry through the browser-level session where your architecture permits.
Rank #4
Related page targets are duplicated
Cause: a tab can have multiple page-like targets, and attach events may be observed more than once. Fix: key related targets by target ID and maintain a one-to-many association instead of overwriting the previous page.
Foreground state appears stale
Cause: no embedder-data change event is emitted. Fix: reissue Target.getTargets or Target.getTargetInfo after relevant user or automation actions; do not wait for Target.targetInfoChanged.
Performance and reliability considerations
- Sort locally after one inventory call rather than repeatedly activating tabs.
- Cache stable identifiers, but refresh active state and order at the points where your workflow depends on them.
- Use bounded timeouts around window and related-target calls so one inaccessible target does not block the inventory.
- Log the raw
embedderDataobject during development. Chromium can add fields, and silently discarding them makes upgrades harder to diagnose. - Test multiple windows, pinned and unpinned tabs, grouped and ungrouped tabs, tabs with more than one page-like target, and user focus changes.
Or skip the browser setup
If your task is obtaining rendered website images rather than inspecting Chrome’s tab strip, ScreenshotNeo provides a one-request screenshot API and MCP server. It is separate from CDP tab metadata, but can remove the need to maintain a browser-launch and capture pipeline.
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 request options. Before capture it accepts cookie/consent banners 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 response headers report the page verdict and billing status. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
FAQ
Does this make CDP equivalent to the Chrome Extensions Tabs API?
No. The report describes Chrome exposing selected tab metadata through CDP target information; it does not claim that CDP now implements the full extensions API.
Can I rely on the fields in every Chromium-based browser?
No. embedderData is designed for the embedder to supply its own metadata. Verify behavior in the specific browser and build you ship.
Is a tab’s active state the same as a page being visible to a user?
It is the browser tab’s foreground state as represented by the reported metadata. Visibility can still be affected by the containing window, operating-system state or other browser behavior.
Frequently Asked Questions
Does this make CDP equivalent to the Chrome Extensions Tabs API?
No. The report describes selected tab metadata exposed through CDP target information, not the full extensions API.
Can every Chromium-based browser expose the same fields?
No. embedderData is supplied by the embedder, so verify the exact browser and build you deploy.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Is tabActive identical to a page being visible to the user?
It represents the tab’s foreground state; window and operating-system state can still affect what is visible.
The Bottom Line
The reported design gives CDP clients a cleaner way to inventory tab order and foreground state: enumerate tab targets, read embedderData, attach related page targets, and resolve windows separately. Treat it as a Canary-dated implementation report, poll for changes, and verify support before deployment.
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.




