Problem: extension pages (popup, options, background page in MV2, etc.) are separate from the web page and they have their own DOM, document, window, and a chrome-extension:// URL.
- Note that service worker doesn't have any DOM/document/window at all.
- To inspect each context of the extension use its own devtools.
Solution: use a content script to access the web page or interact with its contents.
- Content scripts execute in the web page, not in the extension.
- Content scripts are isolated by default, see how to run code in page context (aka MAIN world).
- Don't load your content scripts in the extension page.
Method 1. Declarative
manifest.json:
"content_scripts": [{
  "matches": ["*://*.example.com/*"],
  "js": ["contentScript.js"]
}],
It will run once when the page loads. After that happens, use messaging .
Warning! It can't send DOM elements, Map, Set, ArrayBuffer, classes, functions, and so on. It can only send JSON-compatible simple objects and types so you'll need to manually extract the required data and pass it as a simple array or object.
Method 2. Programmatic
- ManifestV3: - Use chrome.scripting.executeScript in the extension script (like the popup) to inject a content script/function into a tab on demand. - The result of this method is the last expression in the content script so it can be used to extract data. Data must be JSON-compatible, see the warning above. - Required - permissionsin manifest.json:
 - 
- "scripting"- mandatory;
- "activeTab"- ideal scenario, suitable for a response to a user action (usually a click on the extension icon in the toolbar). Doesn't show any permission warning when installing the extension.
 - If ideal scenario is impossible add the allowed sites to - host_permissionsin manifest.json:
 
- ManifestV2 differences to the above: