Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

In brief: Selenium raises “element could not be scrolled into view” when the element it found cannot be placed in a usable, pointer-interactable position. The node may be hidden, zero-sized, disabled, covered by an overlay, inside the wrong frame or shadow root, or moved while the page is rendering. Wait for the correct state, scroll deliberately, verify the element, and locate it again before clicking.

What the error actually means

A Selenium element.click() is a user-like WebDriver action, not merely a JavaScript event. Selenium first tries to scroll the element’s container into view. Its interaction guide says that an out-of-viewport element is aligned with the bottom of the viewport. WebDriver then checks whether the element is interactable and clicks its in-view center point.

If that scroll cannot produce a usable position, Selenium raises ElementNotInteractableException with a message such as “element could not be scrolled into view.” If the center point is visible but another painted element covers it, the protocol uses the separate ElementClickInterceptedException. The fact that a locator returned a node proves only that the node exists in the current DOM; it does not prove that it is visible, enabled, in the viewport, or the node that receives pointer events.

A reliable repair pattern

Use an explicit wait for the application state, center the element to avoid sticky headers, and re-find it after scrolling. This complete example handles the common case:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from selenium import webdriver
from selenium.common.exceptions import (
    ElementClickInterceptedException,
    ElementNotInteractableException,
    StaleElementReferenceException,
    TimeoutException,
)
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

 driver = webdriver.Chrome()
 driver.get("https://example.com/form")
 wait = WebDriverWait(driver, 15)
 locator = (By.CSS_SELECTOR, "button.submit")

 try:
     # Wait for a rendered, visible node rather than DOM presence only.
     button = wait.until(EC.visibility_of_element_located(locator))
     if not button.is_enabled():
         raise RuntimeError("The control is present but disabled")

     # Centering leaves room below a fixed header.
     driver.execute_script(
         "arguments[0].scrollIntoView({block: 'center', inline: 'nearest'});",
         button,
     )

     # Frameworks can replace the node during scrolling; obtain the current one.
     button = wait.until(EC.element_to_be_clickable(locator))
     button.click()
 except (ElementClickInterceptedException, ElementNotInteractableException) as exc:
     raise RuntimeError("Inspect overlays, geometry, and browsing context") from exc
 finally:
     driver.quit()

WebDriverWait polls a callable until it returns a truthy value or the timeout expires. visibility_of_element_located checks that a node is displayed with a usable size; element_to_be_clickable combines visibility and enabled state. Clickability is not a guarantee that an overlay will remain absent between the check and the click, so persistent failures require the diagnostics below.

#1 Best Overall
Elebase USB to USB C Adapter for iPhone 18 Pro Max,USBC Car Charger Adapter
  • Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
  • Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
  • Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
  • Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
  • 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.

Diagnose the element before changing the code

Confirm that the locator selects the right node

Modern applications commonly retain desktop, mobile, template, and duplicate controls in the DOM. Print the count and inspect each match:

matches = driver.find_elements(*locator)
print("matches:", len(matches))
for index, candidate in enumerate(matches):
    print(index, candidate.is_displayed(), candidate.is_enabled(), candidate.size,
          candidate.get_attribute("outerHTML")[:200])

Prefer a semantic <button> or link that receives the event, rather than a decorative <span> nested inside it. If the visible control has a unique label, role, or state, narrow the locator to that control.

Inspect geometry and the hit-test result

button = wait.until(EC.presence_of_element_located(locator))
print("displayed:", button.is_displayed())
print("enabled:", button.is_enabled())
print("size:", button.size)
print(driver.execute_script("""
const e = arguments[0], r = e.getBoundingClientRect();
return {left:r.left, top:r.top, right:r.right, bottom:r.bottom,
        width:r.width, height:r.height,
        viewportWidth:innerWidth, viewportHeight:innerHeight,
        centerElement: document.elementFromPoint(
          r.left + r.width/2, r.top + r.height/2);
""", button))

A zero width or height, a rectangle entirely outside the viewport, or a center element different from the target indicates a layout or overlay problem—not a need for a longer sleep.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Fixes for the common causes

Hidden or zero-size duplicate

Wait for visibility and adjust the locator to the displayed instance. Do not use a hidden template node just because it matches first. A rendered client rectangle and a pointer-interactable paint tree are required for a normal WebDriver click.

Rendering has not finished

A node can exist before its dimensions, position, or enabled state is final. Wait for visibility or clickability, and re-locate after React, Vue, Angular, or another framework re-renders the component. Never retain a WebElement across navigation or a known DOM replacement; that produces a stale-element failure.

Rank #2
Anker USB-C Hub, 5-in-1 USB Hub for Laptops, 4K HDMI Multiport Adapter
  • 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
  • 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
  • Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
  • 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
  • What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.

Fixed header, cookie banner, modal, or spinner

WebDriver clicks the in-view center. Close the obstruction or wait for it to disappear:

cookie = (By.CSS_SELECTOR, ".cookie-banner")
wait.until(EC.invisibility_of_element_located(cookie))
button = wait.until(EC.element_to_be_clickable(locator))
button.click()

Center-aligned scrolling often avoids a sticky header. If a modal or consent layer is legitimate application state, interact with it first rather than forcing the underlying click.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Nested scroll container

An item in a panel with overflow: auto, a virtualized list, or an ancestor with overflow: hidden may not become usable when the document scrolls. Scroll the intended container, wait for the row or item to render, then locate the button again:

panel = wait.until(EC.presence_of_element_located(
    (By.CSS_SELECTOR, ".results-panel")))
driver.execute_script(
    "arguments[0].scrollTop = arguments[0].scrollHeight;", panel)
button = wait.until(EC.element_to_be_clickable(locator))
button.click()

The final requirement is an in-view, hit-testable center point; seeing the page scroll is not sufficient.

Wrong iframe

Elements inside an iframe belong to that frame’s browsing context. Switch before locating them and return to the top-level document afterward:

frame = wait.until(EC.presence_of_element_located(
    (By.CSS_SELECTOR, "iframe.checkout")))
driver.switch_to.frame(frame)
button = wait.until(EC.element_to_be_clickable(
    (By.CSS_SELECTOR, "button.submit")))
button.click()
driver.switch_to.default_content()

If there are nested frames, switch through each one in order. A locator run in the parent document cannot interact with a child frame’s control.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
Sale
Anker USB C Hub, 7in1 Multi-Port USB Adapter, 4K@60Hz USBC to HDMI Splitter
  • Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
  • Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
  • Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
  • Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
  • What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.

Shadow DOM

For an open shadow root, obtain the host’s shadow root and find the descendant there. Interact with the actual control, not the host or a light-DOM placeholder:

host = wait.until(EC.presence_of_element_located(
    (By.CSS_SELECTOR, "checkout-widget")))
shadow = host.shadow_root
button = shadow.find_element(By.CSS_SELECTOR, "button.submit")
wait.until(lambda d: button.is_displayed() and button.is_enabled())
button.click()

Reacquire the host and descendant if the component is rebuilt.

Disabled control

A visible button can still be disabled while validation, loading, or required fields are incomplete. Wait for the application to enable it, and verify the underlying condition instead of clicking repeatedly:

button = wait.until(EC.visibility_of_element_located(locator))
wait.until(lambda d: button.is_enabled())
button.click()

If the element is replaced while enabling, use a locator-based condition again rather than holding the old object.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why fixed sleeps and JavaScript clicks often hide the defect

time.sleep(2) waits the same duration whether the page is ready in 50 milliseconds or still loading after two seconds. It also does not detect an overlay, a disabled state, or a stale node. Explicit waits express the state your test requires.

Rank #4
Sale
UGREEN USB to USB C Adapter Combo 4-Pack, 10Gbps USB C Converter Space Gray
  • Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
  • Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
  • Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
  • Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
  • Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft

A JavaScript click can trigger a DOM click even when a real pointer click would be blocked:

button = wait.until(EC.presence_of_element_located(locator))
driver.execute_script("arguments[0].click();", button)

Use this only when the test intentionally verifies the event handler rather than the user’s ability to reach the control. It bypasses WebDriver hit-testing and can conceal a fixed-header, overlay, disabled-state, or layout bug. It is not equivalent to element.click().

Handle intermittent failures and stale elements

When a framework replaces a node, Selenium’s stored reference points to the old DOM object. Catch the stale condition by retrying a locator-based operation, not by reusing the old reference:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from selenium.common.exceptions import StaleElementReferenceException

def click_current(driver):
    wait = WebDriverWait(driver, 15, ignored_exceptions=(StaleElementReferenceException,))
    target = wait.until(EC.element_to_be_clickable(locator))
    driver.execute_script(
        "arguments[0].scrollIntoView({block:'center'});", target)
    wait.until(EC.element_to_be_clickable(locator)).click()

click_current(driver)

Record the browser and driver versions, Selenium version, viewport size, URL, frame or shadow-root path, and whether the failure is intermittent. Protocol behavior is defined by WebDriver, but a browser-driver combination can expose version-specific timing or layout differences; reproduce it in the supported matrix before adopting a workaround.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

A practical troubleshooting checklist

  • Does the locator select exactly one current, visible control?
  • Are is_displayed(), is_enabled(), dimensions, and the bounding rectangle valid?
  • Has the application reached the required state, rather than merely inserting the node?
  • Are you in the correct iframe and shadow root?
  • Does a cookie banner, modal, spinner, header, or other element cover the center?
  • Is the target inside a nested scroll container or virtualized list?
  • Did a framework re-render the element after you found it?
  • Are you deliberately choosing JavaScript click behavior, or accidentally bypassing a real usability problem?

Or skip the browser setup

If your goal is to capture a page image while diagnosing layout, responsive states, or overlays, ScreenshotNeo returns a screenshot or PDF through one request. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

See the ScreenshotNeo documentation for all options, including full-page and element capture, device and viewport settings, custom CSS and JavaScript, waits, headers, cookies, authentication, blocking rules, PDF output, caching, signed links, asynchronous webhooks, bulk capture, and usage reporting.

Best Value
Anker USB C Hub, 5-in-1 USBC to HDMI Splitter with 4K Display
  • 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
  • Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
  • Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
  • HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
  • What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The Free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 shots, and every feature is included on every plan. Create a free ScreenshotNeo account to try it.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

FAQ

Is this the same as “element click intercepted”?

No. “Could not be scrolled into view” indicates Selenium could not establish a usable in-view position. “Element click intercepted” means another painted element covered the in-view center when WebDriver tried to click.

Should I always use scrollIntoView()?

No. Selenium scrolls as part of a normal click. Explicit centered scrolling is useful when fixed headers, nested layouts, or a page-specific position make the default alignment unreliable.

What details should accompany a bug report?

Include the URL and page state, locator, browser and driver versions, Selenium version, viewport, frame or shadow-root context, exception type, and whether a re-render or overlay was present.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.