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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

A ClassCastException when you cast a Selenium WebElement to Locatable means the object held at runtime does not implement the Locatable interface that your code is using. The reliable fix is to remove the cast when ordinary element methods are all you need, or to verify the concrete element class, interface package, and dependency versions before using coordinate-specific APIs.

Selenium’s current Java API identifies RemoteWebElement as an implementation of both WebElement and Locatable, but a wrapper, proxy, decorator, custom element, or provider-specific object can expose only WebElement. The declared variable type does not determine whether a cast is valid; the runtime object does.

Choose the correct repair first

What your test needs Recommended action Why
Clicking, typing, reading text, attributes, or selecting an element Keep the value as WebElement and call its standard methods Those operations belong to the WebElement API and do not require Locatable.
Coordinates, pointer interactions, or another API that explicitly requires Locatable Confirm the exact interface import and test the runtime type before casting The object may be a wrapper or custom implementation that does not expose Locatable.
The cast works in one environment but fails in another Inspect Selenium versions, class loaders, decorators, and the provider’s element factory Compile-time and runtime Selenium APIs may not be the same.
The element is missing, hidden, or not yet clickable Use the appropriate explicit wait Waiting fixes synchronization, not Java interface compatibility.

What the exception actually means

Java checks a cast against the interfaces implemented by the object, not against the variable declaration. This code can compile:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
WebElement element = driver.findElement(By.id("submit"));
Locatable locatable = (Locatable) element;

It fails at the second line if the object returned by findElement is not an instance of org.openqa.selenium.interactions.Locatable. A normal remote Selenium element is commonly a RemoteWebElement, which the Selenium API lists as a known Locatable implementation. That is not a guarantee for every object typed as WebElement.

Read the complete exception. A useful message normally includes both the actual class and the interface that could not be found, for example:

java.lang.ClassCastException: class com.example.WrappedElement cannot be cast to class org.openqa.selenium.interactions.Locatable

The fully qualified names matter. Older examples, shaded libraries, duplicate Selenium jars, or a different class loader can make an interface with a familiar short name a different runtime type. Compare the import in your source with the API for the Selenium version that is actually running. The official Locatable API reference places the interface in org.openqa.selenium.interactions.

Diagnose the object before changing code

1. Print the concrete class and interfaces

Put this immediately before the failing cast:

WebElement element = driver.findElement(By.id("submit"));

System.out.println("Class: " + element.getClass().getName());
System.out.println("Class loader: " + element.getClass().getClassLoader());
for (Class<?> type : element.getClass().getInterfaces()) {
    System.out.println("Interface: " + type.getName());
}

System.out.println("Supports Locatable: " + (element instanceof Locatable));

If instanceof is false, a direct cast cannot succeed. If it is true but the cast still fails elsewhere, inspect the other object and the exact Locatable import at that location. A proxy may also implement an interface on a superclass, so inspecting the complete class hierarchy can be useful:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
for (Class<?> type = element.getClass(); type != null; type = type.getSuperclass()) {
    System.out.println("Type: " + type.getName());
}

2. Find who supplied or wrapped the element

driver.findElement returns the broad WebElement abstraction. The value may then pass through a page-object decorator, a proxy, a test framework, a remote-grid integration, or a custom element factory. Search for code that replaces, decorates, serializes, or mocks the element. A wrapper that delegates click() and sendKeys() can still omit Locatable.

3. Verify the import and dependency boundary

Use the same Selenium family at compile time and runtime. In Maven, inspect the resolved tree:

mvn dependency:tree -Dincludes=org.seleniumhq.selenium

For Gradle, inspect the runtime classpath:

./gradlew dependencies --configuration testRuntimeClasspath

Look for multiple Selenium versions, an old transitive module, a shaded Selenium class, or a test runner that loads a different copy than the application. Align the modules through one dependency management entry, remove stale transitive versions, then perform a clean rebuild. The exception alone cannot prove that dependency drift is the cause, so confirm it with the class name, class loader, and dependency output.

Fix standard interactions by removing the cast

If the test only has to interact with the DOM element, do not convert it to Locatable:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
WebElement submit = driver.findElement(By.id("submit"));
submit.click();

WebElement email = driver.findElement(By.name("email"));
email.clear();
email.sendKeys("[email protected]");

String label = submit.getText();

These methods are part of Selenium’s WebElement contract. The Selenium documentation covers standard element interactions at Interacting with web elements. Keeping the abstraction as narrow as the operation requires also makes page objects compatible with wrappers and test doubles that correctly implement only WebElement.

Use Locatable only for coordinate-specific work

When a library or your own code genuinely needs coordinates, use the version-correct interface and guard the cast:

import org.openqa.selenium.WebElement;
import org.openqa.selenium.By;
import org.openqa.selenium.interactions.Locatable;

WebElement element = driver.findElement(By.cssSelector(".drag-handle"));
if (!(element instanceof Locatable)) {
    throw new IllegalStateException(
        "Element class " + element.getClass().getName()
        + " does not implement org.openqa.selenium.interactions.Locatable");
}

Locatable locatable = (Locatable) element;
// Call only Locatable methods documented for the Selenium version in use.
// For example, obtain coordinates when that API is available:
var coordinates = locatable.getCoordinates();

Use an explicit type rather than var if your project’s Java level or Selenium signature requires it. Confirm the return type and available methods against the API documentation for your pinned version before copying coordinate code between Selenium releases. If the element is a wrapper, change the wrapper to implement and correctly delegate the required interface, or obtain the underlying Selenium element through the wrapper’s documented API. Do not cast merely to silence a compiler error.

Do not confuse a cast failure with an element-timing failure

A page can finish its load-ready state while JavaScript is still inserting or revealing an element. Selenium’s wait documentation also warns that mixing implicit and explicit waits can produce unpredictable timing. Choose one synchronization strategy deliberately.

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.

Presence: the node exists in the DOM

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement element = wait.until(
    ExpectedConditions.presenceOfElementLocated(By.id("submit")));
element.click();

Selenium defines presence as an element being on the DOM; it does not necessarily mean visible. See the ExpectedConditions Java API.

Visibility: displayed with usable dimensions

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement element = wait.until(
    ExpectedConditions.visibilityOfElementLocated(By.id("submit")));
element.click();

Selenium describes visibility as being displayed with height and width greater than zero. This condition still returns a WebElement; it does not change the object’s implemented interfaces.

Clickability: visible and enabled

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement element = wait.until(
    ExpectedConditions.elementToBeClickable(By.id("submit")));
element.click();

Use this when the control must be both visible and enabled. If the cast fails before or after the wait, the wait is not a repair for the cast. It only addresses readiness.

Common causes and fixes

Symptom Likely cause Action
WebElement cannot be cast to Locatable immediately after a custom page-object lookup Decorator or proxy implements WebElement but not Locatable Remove the cast, or update the decorator to expose the required interface and delegate safely.
The class name is a mock or test-double type The mock was designed for DOM methods only Test behavior through WebElement; configure a coordinate-capable test double only when coordinates are part of the contract.
The source imports a different Locatable package than the runtime API Stale example or incompatible Selenium dependency Use the package documented for the exact Selenium version on both classpaths.
Works locally, fails on a grid or vendor driver Provider-specific element wrapper or different class loader Log the runtime class and class loader in both environments, then inspect the provider’s element implementation.
Changing to an explicit wait does not remove the exception The issue is type compatibility, not timing Resolve the cast branch first; add the appropriate wait separately if the element is not ready.
Several Selenium versions appear in the dependency tree Compile/runtime API mismatch Converge versions, clean the build, and rerun with the same dependency set used to compile.

A repeatable repair workflow

  1. Copy the entire stack trace, including the actual class and interface names.
  2. Record the Selenium Java version, browser driver version, Java version, and execution environment.
  3. Print getClass().getName(), the class loader, and instanceof Locatable for the failing object.
  4. Trace the element from findElement through page objects, decorators, proxies, mocks, and grid adapters.
  5. Remove the cast if the operation is covered by WebElement.
  6. If coordinates are required, verify the exact Locatable import and use a guarded cast only when the runtime object supports it.
  7. Align compile-time and runtime Selenium modules and perform a clean rebuild.
  8. Only after type compatibility is settled, choose presence, visibility, or clickability waits for any separate timing problem.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

How to prevent the error in new code

  • Declare page-object fields as WebElement unless a method truly requires Locatable.
  • Keep coordinate operations in a small adapter so most tests remain independent of implementation-specific interfaces.
  • Make wrappers document which Selenium interfaces they preserve; delegation of methods alone does not preserve interface identity.
  • Pin Selenium modules to a consistent version and review dependency changes in CI.
  • Add a diagnostic assertion at integration boundaries when a provider is expected to return a coordinate-capable element.
  • Do not use a cast as a substitute for a wait, and do not use a wait as a substitute for a compatible object.

Or skip the browser setup

If your goal is to obtain a clean image of a page rather than drive Selenium yourself, ScreenshotNeo provides a single screenshot API request. Its capture pipeline accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

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.

Use the API examples in the ScreenshotNeo documentation:

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 per month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is included on every plan. When browser configuration is the part slowing you down, sign up for the free plan.

FAQ

Does declaring the variable as Locatable make Selenium return a locatable object?

No. A declaration changes the compile-time view of a value; it cannot add an interface to the object created by the driver, wrapper, or proxy.

Can I safely catch ClassCastException and continue?

Usually not. Catching it and silently falling back can hide a broken provider contract. Check the object first with instanceof and fail with a message that identifies the runtime class when coordinate behavior is required.

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

What should I include when reporting this failure?

Include the complete exception, the failing cast line, the fully qualified Locatable import, Selenium and Java versions, the runtime element class, and whether a wrapper, mock, grid, or vendor integration is involved. Those details distinguish an unsupported object from a dependency or class-loader mismatch.

Frequently Asked Questions

Does declaring the variable as Locatable make Selenium return a locatable object?

No. A declaration changes the compile-time view of a value; it cannot add an interface to the object created by the driver, wrapper, or proxy.

Can I safely catch ClassCastException and continue?

Usually not. Check the object with instanceof and fail with a diagnostic message when coordinate behavior is required, rather than hiding a broken provider contract.

What should I include when reporting this failure?

Provide the complete exception, failing cast line, fully qualified Locatable import, Selenium and Java versions, runtime element class, and any wrapper, mock, grid, or vendor integration.

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

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.