Current package version
pydoll-python 2.23.1
Checklist before requesting
Problem Statement
Chrome 150 now exposes the real browser-UI state of tabs through CDP. Pydoll should provide a read-only way to answer questions such as:
- Which tab is selected in each Chrome window?
- What is each tab's tab-strip position?
- Is it pinned or grouped?
- Which Chrome window contains it?
- Which Pydoll
Tab / page target belongs to it?
This matters when Pydoll connects to a user-owned browser or shares a headed browser with a human. Today ChromiumBase.get_opened_tabs() enumerates "page" targets and returns Tab objects, but a page target is not the browser's tab UI object, and target enumeration order is not tab-strip or focus order.
Before Chrome 150, CDP did not expose authoritative browser-UI tab state. document.hasFocus(), document.visibilityState, focus/blur listeners, or scripts installed with Page.addScriptToEvaluateOnNewDocument only observe or alter renderer state. Page.bringToFront and Target.activateTarget mutate state and may also raise the native browser window; they cannot answer which tab was active without disturbing the user. Backgrounding flags affect scheduling, not tab selection.
That distinction also explains the confusion in #241: tab activation, DOM element focus, and bringing the Chrome application to the OS foreground are different operations.
Proposed Solution
Chrome 150 Stable adds Target.TargetInfo.embedderData for targets of type "tab". A client can request only those targets:
result = await connection.execute_command(
TargetCommands.get_targets(
filter=[
{"type": "tab", "exclude": False},
{"exclude": True},
]
)
)
Each tab target may contain:
{
"embedderData": {
"tabStripIndex": 0,
"tabActive": True,
"tabPinned": False,
"tabGroupId": "...", # optional
}
}
Pydoll's TargetInfo model currently omits embedderData, although TargetCommands.get_targets() already accepts a filter. A useful implementation could:
- add forward-compatible parsing for
TargetInfo.embedderData and a typed TabInfo snapshot;
- enumerate
"tab" targets and order them by tabStripIndex within each Chrome window;
- use
Browser.getWindowForTarget for the Chrome window ID;
- map a tab target to its related page target(s), without assuming one tab equals one page; and
- expose this separately from mutating activation APIs.
Possible public shapes:
tab_info = await tab.get_tab_info()
# TabInfo(active=True, index=0, pinned=False, group_id=None, window_id=1)
tabs = await browser.get_tabs()
active_tabs = await browser.get_active_tabs() # one selected tab per Chrome window
Another option is to evolve get_opened_tabs() so it can return tab-strip ordering and metadata, but keeping browser-UI tab targets distinct from Pydoll's current page-target-backed Tab abstraction may be less surprising.
The API should gracefully return None / unavailable metadata on Chrome versions before 150 and embedders that omit the field. Unknown future keys in embedderData should not break parsing.
Important protocol details:
- Metadata belongs to
"tab" targets, not "page" targets.
- A tab can contain multiple page targets under Chromium's multi-page architecture.
Target.autoAttachRelated can discover related targets.
- The data is currently pull-based; metadata-only changes do not emit new
Target.targetInfoChanged events.
tabActive means selected in its containing Chrome window. It does not mean that Chrome is the OS foreground application.
References:
Alternatives Considered
- Treating the last result from
get_opened_tabs() as current: target order is not tab-strip or focus order.
document.hasFocus(), visibilityState, focus events, or an injected tracking/forcing script: renderer-level and not authoritative browser UI state.
Page.bringToFront / Target.activateTarget: useful explicit mutations, but they steal/change focus and cannot be used for discovery.
Emulation.setFocusEmulationEnabled: changes renderer focus semantics; it does not report the selected tab.
--disable-backgrounding-occluded-windows, --disable-renderer-backgrounding, and --disable-background-timer-throttling: mitigate throttling but do not expose tab selection.
- A Chrome extension using
chrome.tabs: works in some deployments but should not be required for a CDP-native library.
Additional Context
Related Pydoll threads:
Pydoll already ships the relevant activation commands and launches Chrome with background timer/occluded-window flags in its test setup. Those mechanisms can remain unchanged. Reading tabActive should be an independent capability, so callers can observe the user's selected tab without forcing focus or changing page behavior.
Importance
Important
Contribution
I could help with parts of the implementation
Current package version
pydoll-python2.23.1Checklist before requesting
Problem Statement
Chrome 150 now exposes the real browser-UI state of tabs through CDP. Pydoll should provide a read-only way to answer questions such as:
Tab/ page target belongs to it?This matters when Pydoll connects to a user-owned browser or shares a headed browser with a human. Today
ChromiumBase.get_opened_tabs()enumerates"page"targets and returnsTabobjects, but a page target is not the browser's tab UI object, and target enumeration order is not tab-strip or focus order.Before Chrome 150, CDP did not expose authoritative browser-UI tab state.
document.hasFocus(),document.visibilityState, focus/blur listeners, or scripts installed withPage.addScriptToEvaluateOnNewDocumentonly observe or alter renderer state.Page.bringToFrontandTarget.activateTargetmutate state and may also raise the native browser window; they cannot answer which tab was active without disturbing the user. Backgrounding flags affect scheduling, not tab selection.That distinction also explains the confusion in #241: tab activation, DOM element focus, and bringing the Chrome application to the OS foreground are different operations.
Proposed Solution
Chrome 150 Stable adds
Target.TargetInfo.embedderDatafor targets of type"tab". A client can request only those targets:Each tab target may contain:
{ "embedderData": { "tabStripIndex": 0, "tabActive": True, "tabPinned": False, "tabGroupId": "...", # optional } }Pydoll's
TargetInfomodel currently omitsembedderData, althoughTargetCommands.get_targets()already accepts a filter. A useful implementation could:TargetInfo.embedderDataand a typedTabInfosnapshot;"tab"targets and order them bytabStripIndexwithin each Chrome window;Browser.getWindowForTargetfor the Chrome window ID;Possible public shapes:
Another option is to evolve
get_opened_tabs()so it can return tab-strip ordering and metadata, but keeping browser-UI tab targets distinct from Pydoll's current page-target-backedTababstraction may be less surprising.The API should gracefully return
None/ unavailable metadata on Chrome versions before 150 and embedders that omit the field. Unknown future keys inembedderDatashould not break parsing.Important protocol details:
"tab"targets, not"page"targets.Target.autoAttachRelatedcan discover related targets.Target.targetInfoChangedevents.tabActivemeans selected in its containing Chrome window. It does not mean that Chrome is the OS foreground application.References:
Alternatives Considered
get_opened_tabs()as current: target order is not tab-strip or focus order.document.hasFocus(),visibilityState, focus events, or an injected tracking/forcing script: renderer-level and not authoritative browser UI state.Page.bringToFront/Target.activateTarget: useful explicit mutations, but they steal/change focus and cannot be used for discovery.Emulation.setFocusEmulationEnabled: changes renderer focus semantics; it does not report the selected tab.--disable-backgrounding-occluded-windows,--disable-renderer-backgrounding, and--disable-background-timer-throttling: mitigate throttling but do not expose tab selection.chrome.tabs: works in some deployments but should not be required for a CDP-native library.Additional Context
Related Pydoll threads:
Page.bringToFront,Target.activateTarget, DOM focus, and the desire to foreground the entire browser. The new metadata solves only read-only tab discovery; it does not provide OS-window foregrounding.Page.addScriptToEvaluateOnNewDocumentusage. Such scripts remain useful for initialization, but cannot reliably replace browser-provided tab-strip metadata.Pydoll already ships the relevant activation commands and launches Chrome with background timer/occluded-window flags in its test setup. Those mechanisms can remain unchanged. Reading
tabActiveshould be an independent capability, so callers can observe the user's selected tab without forcing focus or changing page behavior.Importance
Important
Contribution
I could help with parts of the implementation