Skip to content
Independent guides for QA & test automationRSSEditorial policy
QA Vibes

Element Click Intercepted: "Other element would receive the click" in Selenium, and "intercepts pointer events" in Playwright

One overlay, two tools: Sauce Demo's slide-out menu covers the product images, and clicking one fails in Selenium with ElementClickInterceptedException and in Playwright with a timeout whose call log says "intercepts pointer events". Why elementToBeClickable doesn't help, why closing the menu and clicking at once was flaky in Selenium and not in Playwright, and why force and JavaScript clicks are the wrong fix.

QA Vibes EditorialPublished 12 minTested with Playwright 1.63.0, Chromium 153, Selenium 4.49.0, Chrome 154, Java 21, JUnit 6.1.3Revision history ↓

Key takeaways

  • Both errors mean the same thing: something else is on top of the element at the point the click would land, and the message names it. Here it was Sauce Demo's open menu, <nav class="bm-item-list">.
  • Selenium fails at once; Playwright retries until the element is uncovered or its timeout runs out, so the same mistake shows up as a timeout with "intercepts pointer events" in the call log.
  • ExpectedConditions.elementToBeClickable() passed for the covered image, and the click right after it still threw. It checks visible and enabled, not what's on top.
  • Closing the menu and clicking at once failed 5 times in 20 Selenium runs, and passed 10 of 10 in Playwright, which retried through the slide-out animation.
  • force: true clicked the menu instead, and a JavaScript click passed although no user could click the image. Remove the overlay the way a user would.
Contents (8 sections)

Introduction

"element click intercepted: Element … is not clickable at point (170, 274). Other element would receive the click" is Selenium's ElementClickInterceptedException. Playwright reports the same situation differently: the click waits, and its call log repeats "… subtree intercepts pointer events" until a timeout. Both mean that another element sits on top of the one you want to click, at the exact point where the click would land.

This page reproduces both on one real page, Sauce Demo's products list with its slide-out menu open, and measures the usual fixes. It was all run on 13 October 2026: Playwright 1.63.0 with its Chromium 153, and Selenium 4.49.0 with JUnit 6.1.3 and Java 21 against Chrome 154, headless, in a 1280 × 720 window.

The overlay

Sauce Demo's "Open Menu" button slides a 300-pixel menu in from the left. It has no dimmed backdrop, so the page beside it still looks clickable, but the menu covers the left part of the first product, including the Sauce Labs Backpack's image link (data-test="item-4-img-link"). The "Add to cart" buttons, further right, are not covered, which is why this goes unnoticed in tests that only add products.

A test that opens the menu, checks something in it, and then carries on with the products is the realistic way in. In each test below, the menu is opened and fully slid in before the click on the image.

Selenium: "element click intercepted"

The Maven dependencies:

<dependencies>
  <dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.49.0</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>6.1.3</version>
    <scope>test</scope>
  </dependency>
</dependencies>

src/test/java/MenuClickTest.java holds both the mistakes and the fixes, so one run shows them side by side:

import java.time.Duration;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.ElementClickInterceptedException;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
 
class MenuClickTest {
    // Sauce Demo publishes this password on its own login page.
    private static final String PASSWORD = System.getenv().getOrDefault("SAUCE_PASSWORD", "secret_sauce");
    private static final By BACKPACK_IMAGE = By.cssSelector("[data-test='item-4-img-link']");
    private static final By CLOSE_MENU = By.id("react-burger-cross-btn");
 
    private WebDriver driver;
    private WebDriverWait wait;
 
    @BeforeEach
    void logInAndOpenTheMenu() {
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--headless=new", "--window-size=1280,720");
        driver = new ChromeDriver(options);
        wait = new WebDriverWait(driver, Duration.ofSeconds(10));
        driver.get("https://www.saucedemo.com/");
        driver.findElement(By.id("user-name")).sendKeys("standard_user");
        driver.findElement(By.id("password")).sendKeys(PASSWORD);
        driver.findElement(By.id("login-button")).click();
        driver.findElement(By.id("react-burger-menu-btn")).click();
        wait.until(ExpectedConditions.elementToBeClickable(By.id("about_sidebar_link")));
    }
 
    @AfterEach
    void quit() {
        driver.quit();
    }
 
    /** Clicks, retrying for as long as the wait allows while another element is on top. */
    private void clickWhenNotCovered(By locator) {
        wait.ignoring(ElementClickInterceptedException.class)
            .withMessage(locator + " stayed covered by another element")
            .until(d -> {
                d.findElement(locator).click();
                return true;
            });
    }
 
    @Test
    void opensTheBackpackWithTheMenuOpen() {
        driver.findElement(BACKPACK_IMAGE).click();
        wait.until(ExpectedConditions.urlContains("inventory-item.html?id=4"));
    }
 
    @Test
    void waitsUntilClickableFirst() {
        wait.until(ExpectedConditions.elementToBeClickable(BACKPACK_IMAGE)).click();
        wait.until(ExpectedConditions.urlContains("inventory-item.html?id=4"));
    }
 
    @RepeatedTest(10)
    void closesTheMenuThenClicksAtOnce() {
        driver.findElement(CLOSE_MENU).click();
        driver.findElement(BACKPACK_IMAGE).click();
        wait.until(ExpectedConditions.urlContains("inventory-item.html?id=4"));
    }
 
    @RepeatedTest(10)
    void closesTheMenuThenRetriesTheClick() {
        driver.findElement(CLOSE_MENU).click();
        clickWhenNotCovered(BACKPACK_IMAGE);
        wait.until(ExpectedConditions.urlContains("inventory-item.html?id=4"));
    }
 
    @Test
    void retriesWithTheMenuStillOpen() {
        clickWhenNotCovered(BACKPACK_IMAGE);
        wait.until(ExpectedConditions.urlContains("inventory-item.html?id=4"));
    }
 
    @Test
    void javascriptClickWithTheMenuOpen() {
        ((JavascriptExecutor) driver).executeScript("arguments[0].click();", driver.findElement(BACKPACK_IMAGE));
        wait.until(ExpectedConditions.urlContains("inventory-item.html?id=4"));
    }
}

mvn test ran 24 tests (the two repeated tests count ten each) and reported 4 errors:

[ERROR] Tests run: 24, Failures: 0, Errors: 4, Skipped: 0
[ERROR] MenuClickTest.closesTheMenuThenClicksAtOnce()[1] -- Time elapsed: 5.054 s <<< ERROR!
[ERROR] MenuClickTest.retriesWithTheMenuStillOpen -- Time elapsed: 13.84 s <<< ERROR!
[ERROR] MenuClickTest.opensTheBackpackWithTheMenuOpen -- Time elapsed: 4.314 s <<< ERROR!
[ERROR] MenuClickTest.waitsUntilClickableFirst -- Time elapsed: 4.189 s <<< ERROR!

(Each time includes starting Chrome and logging in, about 3 seconds.)

Reading the message

The plain click with the menu open failed at once:

org.openqa.selenium.ElementClickInterceptedException:
element click intercepted: Element <a href="#" id="item_4_img_link" data-test="item-4-img-link" role="button" aria-label="View details for Sauce Labs Backpack">...</a> is not clickable at point (170, 274). Other element would receive the click: <nav class="bm-item-list" style="height: 100%;">...</nav>
  (Session info: chrome=154.0.8037.98)

It has three parts, and the last one is the answer:

  • The element you asked for, here the backpack's image link. If this isn't what you expected, the locator is the problem, not the overlay.
  • The point Selenium tried to click, (170, 274): the centre of the part of the element that is inside the window, in window coordinates.
  • "Other element would receive the click": what is on top at that point. Here it's <nav class="bm-item-list">, the menu's list. Search your page for that element. A modal, a cookie banner, a sticky header, a loading spinner or a toast are the usual answers.

elementToBeClickable doesn't check what's on top

waitsUntilClickableFirst waited with ExpectedConditions.elementToBeClickable(BACKPACK_IMAGE). The wait passed straight away, and the click right after it threw the same ElementClickInterceptedException. The condition checks that the element is displayed and enabled. A covered element is both. The name suggests more than it does, and "wait until clickable" is the most common answer to this error: Selenium's own troubleshooting page suggests it too. On this page it made no difference.

Closing the menu and clicking at once was flaky

The menu takes half a second to slide out after "Close Menu". closesTheMenuThenClicksAtOnce clicked the image straight after closing it, while the menu could still be over the image. In this run 1 of 10 failed, with the same message naming <nav class="bm-item-list">. In an earlier batch of ten with the same steps, 4 failed. That's 5 in 20: a test that passes most of the time and fails on a slow day, which is how this error usually reaches a CI log.

Selenium doesn't retry a click. It checks what's on top once, at the moment of the click, and throws if it's the wrong element.

The fix: remove the overlay, then retry only this exception

closesTheMenuThenRetriesTheClick closes the menu, as a user would, and then clicks with clickWhenNotCovered: a WebDriverWait that ignores ElementClickInterceptedException and tries again every 500 ms for up to 10 seconds. It passed 10 of 10 in this run, and 10 of 10 in the earlier batch.

The retry only helps when the overlay is on its way out. retriesWithTheMenuStillOpen uses the same helper without closing the menu, and it failed after its 10 seconds, with a message that says what happened and the original exception as the cause:

org.openqa.selenium.TimeoutException:
Expected condition failed: By.cssSelector: [data-test='item-4-img-link'] stayed covered by another element
(tried for 10 seconds with 500 milliseconds interval)
Caused by: org.openqa.selenium.ElementClickInterceptedException:
element click intercepted: Element <a href="#" id="item_4_img_link" data-test="item-4-img-link" role="button" aria-label="View details for Sauce Labs Backpack">...</a> is not clickable at point (170, 274). Other element would receive the click: <nav class="bm-item-list" style="height: 100%;">...</nav>

Without .withMessage(...), the first line names a lambda, which tells you nothing. Ignore only ElementClickInterceptedException in a wait like this. Ignoring every WebDriverException would also hide a wrong locator for 10 seconds.

A wait for the menu to disappear didn't work here. ExpectedConditions.invisibilityOfElementLocated(By.id("about_sidebar_link")) timed out after 10 seconds in each of the eight runs that got that far, because Sauce Demo slides the menu off screen without hiding it, and Selenium still counts an element off screen to the left as displayed. Check what the overlay actually does when it closes before you write a wait for it.

The JavaScript click passed, and shouldn't have

javascriptClickWithTheMenuOpen clicked with arguments[0].click(), with the menu still open, and passed: the product page opened. A JavaScript click calls the element's click handler directly. It doesn't care what is on top, so it doesn't test whether a user can click the image. Here a user couldn't. This is the fix most forum answers end with, and it turns a test that found a covered element into one that can't.

Playwright: "subtree intercepts pointer events"

The same steps in Playwright. The config sets testIdAttribute for Sauce Demo's data-test attributes, and an action timeout so a stuck click fails at the click (the timeout errors guide explains why that's worth setting):

import { defineConfig } from "@playwright/test";
 
export default defineConfig({
  testDir: "./tests",
  reporter: "list",
  use: { testIdAttribute: "data-test", actionTimeout: 10_000 },
});

tests/menu.spec.ts:

import { test, expect } from "@playwright/test";
 
// Sauce Demo publishes this password on its own login page.
const PASSWORD = process.env.SAUCE_PASSWORD ?? "secret_sauce";
 
test.beforeEach(async ({ page }) => {
  await page.goto("https://www.saucedemo.com/");
  await page.getByPlaceholder("Username").fill("standard_user");
  await page.getByPlaceholder("Password").fill(PASSWORD);
  await page.getByRole("button", { name: "Login" }).click();
  await page.getByRole("button", { name: "Open Menu" }).click();
  // A trial click waits until the link is visible and stable: the menu has finished sliding in.
  await page.getByRole("link", { name: "About" }).click({ trial: true });
});
 
test("opens the backpack with the menu still open", async ({ page }) => {
  await page.getByTestId("item-4-img-link").click();
  await expect(page).toHaveURL(/inventory-item\.html\?id=4$/);
});
 
test("closes the menu, then opens the backpack", async ({ page }) => {
  await page.getByRole("button", { name: "Close Menu" }).click();
  await page.getByTestId("item-4-img-link").click();
  await expect(page).toHaveURL(/inventory-item\.html\?id=4$/);
});

The click waits, then times out

With the menu open, the click didn't fail at once. Playwright checks what's on top of the element too, but when it finds something else there, it waits and tries again. After the 10-second action timeout:

TimeoutError: locator.click: Timeout 10000ms exceeded.
Call log:
  - waiting for getByTestId('item-4-img-link')
    - locator resolved to <a href="#" role="button" id="item_4_img_link" data-test="item-4-img-link" aria-label="View details for Sauce Labs Backpack">…</a>
  - attempting click action
    2 × waiting for element to be visible, enabled and stable
      - element is visible, enabled and stable
      - scrolling into view if needed
      - done scrolling
      - <nav class="bm-item-list">…</nav> from <header id="header_container" class="header_container" data-test="header-container">…</header> subtree intercepts pointer events
    - retrying click action
    - waiting 20ms

(The log goes on in the same way, retrying after 100 ms and then every 500 ms, until the timeout.) The first line only says the click ran out of time. The call log says why: the element was visible, enabled and stable, and <nav class="bm-item-list"> inside <header id="header_container"> would have received the click. Some retries name dynamic_catalog_sidebar_link instead, a link inside the menu, because that's what was under the click point at that moment. Without actionTimeout in the config, the same click retried until the 30-second test timeout, and the report started with "Test timeout of 30000ms exceeded." followed by "Error: locator.click: Test timeout of 30000ms exceeded."; the call log still said "intercepts pointer events", so search for that either way.

Closing the menu first passed, every time

The second test closed the menu and clicked at once, the step that was flaky in Selenium. It passed 10 of 10 with --repeat-each=10. Playwright's API log for one run (DEBUG=pw:api) shows why: the click found <nav class="bm-item-list"> on top three times while the menu slid out, retried, and then clicked the image. The retry that the Selenium helper adds by hand is built into every Playwright action.

That retry is also why Playwright can hide this problem rather than report it. A click that becomes possible a second later passes, so an overlay that delays users for a second goes unnoticed. If the delay matters, assert it.

force: true clicked the menu

click({ force: true }) skips Playwright's checks, including what's on top. With the menu open, it failed, but not at the click:

Error: expect(page).toHaveURL(expected) failed
 
Expected pattern: /inventory-item\.html\?id=4$/
Received string:  "https://www.saucedemo.com/inventory.html"
Timeout: 5000ms

A forced click still clicks at a point on the screen, and the menu was what was at that point, so the menu got the click and the product page never opened. dispatchEvent("click"), Playwright's equivalent of the JavaScript click, passed with the menu open, for the same reason as in Selenium: it fires the element's click handler without involving the screen at all. These are the two in tests/bypass.spec.ts:

import { test, expect } from "@playwright/test";
 
// Sauce Demo publishes this password on its own login page.
const PASSWORD = process.env.SAUCE_PASSWORD ?? "secret_sauce";
 
test.beforeEach(async ({ page }) => {
  await page.goto("https://www.saucedemo.com/");
  await page.getByPlaceholder("Username").fill("standard_user");
  await page.getByPlaceholder("Password").fill(PASSWORD);
  await page.getByRole("button", { name: "Login" }).click();
  await page.getByRole("button", { name: "Open Menu" }).click();
  await page.getByRole("link", { name: "About" }).click({ trial: true });
});
 
test("force: true, menu open", async ({ page }) => {
  await page.getByTestId("item-4-img-link").click({ force: true });
  await expect(page).toHaveURL(/inventory-item\.html\?id=4$/);
});
 
test("dispatchEvent, menu open", async ({ page }) => {
  await page.getByTestId("item-4-img-link").dispatchEvent("click");
  await expect(page).toHaveURL(/inventory-item\.html\?id=4$/);
});

A wait that didn't wait

Our first attempt at a Playwright fix waited for the menu to close with expect(page.getByRole("link", { name: "About" })).toBeHidden(). It passed 31 ms after the click on "Close Menu", while the menu still had most of its half-second slide ahead of it. Sauce Demo sets aria-hidden="true" on the menu when it starts closing, and role locators skip elements hidden from assistive technology, so the link stopped matching at once. The test then passed only because the click retried. It's the opposite of Selenium's problem with the same menu: one tool thought it was gone too early, the other never thought it was gone.

How to prevent it

  • Read the "other element". Both tools name what was on top. Decide whether a user would see it there too. If they would, the test is missing a step; if they wouldn't, the page has a bug worth a report.
  • Remove the overlay the way a user does. Close the menu, dismiss the cookie banner, wait for the spinner's request to finish. The step belongs in the test, or in the page object method that opened the overlay.
  • In Selenium, retry only ElementClickInterceptedException, with a limit and a message. Animations that move an overlay away need it, because Selenium checks once. elementToBeClickable is not that check.
  • In Playwright, let the click retry, and set an action timeout. Then a click that stays covered fails in 10 seconds with the overlay in the call log, instead of at the 30-second test timeout.
  • Don't force it. force: true, dispatchEvent and JavaScript clicks make the test stop checking that the element can be clicked, which is the thing that failed. Our Playwright test reviewer flags force: true for that reason.

Exercise

Open Sauce Demo's menu in your own test, and click "Add to cart" for the Backpack instead of its image. Predict, before running it, whether Selenium throws and whether Playwright waits, then check. Then shrink the window to 375 pixels wide and predict again. The answer depends on what the menu covers at each size, and the "other element" in the message will tell you.

If the element you clicked was replaced rather than covered, the error is StaleElementReferenceException in Selenium and "Element is not attached to the DOM" in Playwright. For more of Sauce Demo's own errors, the Sauce Demo error messages reference lists every message the site shows, and the practice lab runs your tests against a shop with seeded bugs.

Conclusion

"Other element would receive the click" and "intercepts pointer events" are the same finding: at the point where the click lands, something else is on top, and the message names it. Selenium reports it at once and doesn't retry; Playwright retries until its timeout, so the same problem arrives as a timeout with the cause in the call log. Fix it by removing the overlay as a user would and, in Selenium, by retrying only that exception while the overlay moves away. A forced or JavaScript click passes a test that a user would fail.

Sources and further reading

Tools mentioned

SeleniumUI AutomationOpen source
PlaywrightUI AutomationOpen source

Links go to each tool’s official site. How we choose and link tools

Revision history

First published.

Spotted a mistake? Report it — corrections land here.

Written and reviewed by

QA Vibes Editorial

Articles are written and reviewed by practicing QA and automation engineers. Every article lists its sources and shows when it was last updated.

Check your own tests

Playwright test reviewer

Paste a test to find fixed waits, missing awaits, and assertions that can never fail.