#
Disable closed Shadow DOMs
This tutorial shows you how to force every closed Shadow DOM on visited pages to open so your automation code can query inside without custom execution contexts. You'll enable the forceOpenShadowRoot feature, start a profile, validate it works, and learn the trade‑offs.
#
Prerequisites
- Completion of the Quickstart guide
- Kameleo app is running locally (default API base URL:
http://localhost:5050).
#
Understand the feature
Modern web apps encapsulate DOM and styles in Shadow Roots. Closed shadow roots cannot be traversed via standard DOM APIs; you must call custom element methods. Kameleo can patch kernels to expose closed roots as if they were open, simplifying selectors for scraping, testing, and CAPTCHA widget handling.
Side effects
Opening all closed roots may: (1) expose implementation details sites rely on staying private, (2) cause fragile selectors if a site later restructures components. Use only when you specifically need access closed roots.
#
Option 1: Enable when starting a profile (SDKs)
Set kameleo:forceOpenShadowRoot = true in the browser start settings / request body when calling the start endpoint.
from kameleo.local_api_client.models import BrowserSettings, Preference
# Assume an existing profile object or create one beforehand
client.profile.start_profile(profile.id, BrowserSettings(
additional_options=[Preference(key='kameleo:forceOpenShadowRoot', value=True)]
))
print('Profile started with forced open shadow roots')
await client.profile.startProfile(profile.id, {
additionalOptions: [{ key: "kameleo:forceOpenShadowRoot", value: true }],
});
console.log("Profile started with forced open shadow roots");
using System.Collections.Generic;
using Kameleo.LocalApiClient.Model;
await client.Profile.StartProfileAsync(profile.Id, new BrowserSettings
{
AdditionalOptions = new List<Preference> { new Preference("kameleo:forceOpenShadowRoot", true) }
});
Console.WriteLine("Profile started with forced open shadow roots");
#
Option 2: Enable through Selenium WebDriver capability
Add the custom capability kameleo:forceOpenShadowRoot: true (alongside kameleo:profileId).
from selenium import webdriver
caps = {
'kameleo:profileId': profile_id, # existing profile id
'kameleo:forceOpenShadowRoot': True,
'browserName': 'Kameleo'
}
driver = webdriver.Remote(command_executor='http://localhost:5050/webdriver', desired_capabilities=caps)
import { Builder } from "selenium-webdriver";
const driver = await new Builder()
.usingServer("http://localhost:5050/webdriver")
.withCapabilities({
"kameleo:profileId": profile.id,
"kameleo:forceOpenShadowRoot": true,
browserName: "Kameleo",
})
.build();
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
var caps = new OpenQA.Selenium.Remote.DesiredCapabilities();
caps.SetCapability("kameleo:profileId", profileId);
caps.SetCapability("kameleo:forceOpenShadowRoot", true);
caps.SetCapability("browserName", "Kameleo");
var driver = new RemoteWebDriver(new Uri("http://localhost:5050/webdriver"), caps);
#
5. Validate
- Navigate to a site known to use closed shadow roots (e.g., Cloudflare Turnstile).
- Open DevTools Console and run:
// All shadow roots should be accessible
[...document.querySelectorAll("*")]
.map((el) => el.shadowRoot)
.filter((r) => r)
.slice(0, 5);
If objects are returned for components that normally have closed roots, the feature works.