2026, Jan 03 09:00

How to Dismiss Cookie Banners in iframes with Selenium WebDriver: Switch Context and Click Reject All

Handle cookie banners inside iframes on autotrader.co.uk with Selenium WebDriver: switch to the consent iframe, click Reject All, then return for stable tests.

Cookie banners are often the first thing your Selenium tests run into. On autotrader.co.uk the consent dialog sits inside an iframe, so a naive click on the Reject All button won’t work: the driver is looking in the wrong DOM.

Reproducing the issue

The following script launches Chrome, opens the site and tries to click the cookie banner. Despite an explicit wait, the pop-up doesn’t go away.

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

exe_bin = r"C:\path_to_project\chromedriver.exe"
svc_mgr = Service(executable_path=exe_bin)

browser = webdriver.Chrome(service=svc_mgr)
browser.get("https://www.autotrader.co.uk")
time.sleep(5)
WebDriverWait(browser, 15).until(
    EC.element_to_be_clickable((By.CLASS_NAME, 'message-component message-button no-children focusable sp_choice_type_13'))
).click()

time.sleep(10)
browser.quit()

What actually blocks the click

The cookie dialog is rendered inside an iframe. Selenium only searches within the current context, and by default that context is the top-level document. Until the driver switches into the iframe, any locator that targets elements inside it won’t resolve. There’s another nuance: the iframe’s id is not static, so a robust locator should use a partial match rather than a hardcoded value.

The fix: switch context, then click

The workflow is straightforward. Wait until the iframe is ready and switch into it. Inside that context, wait for the Reject All button and click it. When done, return to the main page so the rest of the script can interact with the top-level DOM.

import time
from selenium.webdriver import Chrome, ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

opts = ChromeOptions()
opts.add_experimental_option("excludeSwitches", ['enable-automation'])
client = Chrome(options=opts)

client.get("https://www.autotrader.co.uk")
waiter = WebDriverWait(client, 10)

# switch into the dynamically-named consent iframe
waiter.until(
    EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, 'iframe[id^="sp_message_iframe_"]'))
)

# click the 'Reject All' button inside the iframe
waiter.until(
    EC.element_to_be_clickable((By.XPATH, '//button[@title="Reject All"]'))
).click()

# return to the top-level document
client.switch_to.default_content()

time.sleep(5)

Why this matters for stable automation

Consent managers and other overlays are frequently embedded via iframes. Without switching the driver context, locators silently target the wrong DOM and interactions never happen. Handling dynamic iframe ids with a partial-match selector avoids brittle code that fails as soon as the provider regenerates identifiers.

Wrap-up

Before you fight a stubborn element, check whether it lives in an iframe. Use an explicit wait to switch into it, operate on the target control, and switch back with default_content to continue. For dynamic attributes like iframe ids, prefer CSS or XPath partial matches. This small bit of discipline keeps your Selenium flows resilient on pages that outsource UI fragments, including cookie banners.