A ClassCastException such as WebElement cannot be cast to Locatable occurs because the object held at runtime does not implement the Locatable interface that your code is trying to use. The variable’s declared type, WebElement, does not guarantee that every implementation can be cast to Locatable. Remove the cast when ordinary element methods are sufficient; otherwise verify the concrete element class, the exact Selenium API package, and dependency consistency before changing code.
What the casting error actually means
Java checks casts against the interfaces implemented by the object created at runtime. For example:
WebElement element = driver.findElement(By.id("submit"));
Locatable locatable = (Locatable) element;
The second line succeeds only when the object behind element implements the same Locatable interface visible to the running application. Selenium’s current Java API documents RemoteWebElement as implementing both WebElement and Locatable, and identifies it as the known implementation of Locatable (RemoteWebElement API; Locatable API). That does not make every object returned, wrapped, or supplied as a WebElement cast-safe.
Why a WebElement may not be Locatable
- A custom
WebElementimplementation exposes only the methods required by that interface. - A decorator, proxy, mock, or wrapper hides the underlying remote element and does not implement
Locatable. - A grid or provider-specific element factory returns a different implementation.
- Your code imports a
Locatabletype from a package or Selenium version that does not match the runtime classes.
The declared type controls what methods the compiler permits; the runtime class controls whether a cast is legal.
Fix the common case: remove the cast
If you only need to click, type, read text, select, or inspect attributes, use the WebElement API directly. Selenium documents these operations as part of WebElement (Interacting with web elements).
WebElement submit = driver.findElement(By.id("submit"));
submit.click();
WebElement search = driver.findElement(By.name("q"));
search.clear();
search.sendKeys("Selenium Java");
System.out.println(search.getAttribute("value"));
Do not cast merely to call a method that already exists on WebElement. This is the safest repair because it works with remote elements, wrappers, and test doubles that correctly implement the standard interface.
If you genuinely need Locatable
Locatable is relevant to coordinate- or location-specific behavior. Before using it, confirm all three conditions:
Rank #2
- The operation truly requires location information rather than a normal DOM interaction.
- The object’s concrete runtime class implements the
Locatableinterface used by your Selenium version. - The compile-time and runtime Selenium modules resolve to a compatible, consistent version.
Inspect the actual object and interface
WebElement element = driver.findElement(By.id("submit"));
System.out.println("Runtime class: " + element.getClass().getName());
System.out.println("WebElement interfaces:");
for (Class<?> type : element.getClass().getInterfaces()) {
System.out.println(" - " + type.getName());
}
if (element instanceof Locatable) {
Locatable locatable = (Locatable) element;
// Use the Locatable operation required by your pinned Selenium version.
} else {
throw new IllegalStateException(
"Element implementation does not implement " + Locatable.class.getName());
}
The class name often reveals a decorator, proxy, mock, or provider implementation. If it is not the expected Selenium remote element, trace where the object was created and whether a wrapper can expose the underlying element safely. Avoid forcing a cast with reflection or an unrelated interface; that only moves the failure to a later operation.
Verify the import and dependency graph
Use the Locatable package documented for the Selenium Java version pinned by your project. The API reference places it in org.openqa.selenium.interactions, but old examples may target a different API arrangement. Check the dependency tree and the resolved JARs, not just the version written in a build file.
For Maven, inspect:
mvn dependency:tree -Dincludes=org.seleniumhq.selenium
For Gradle, inspect:
./gradlew dependencies --configuration testRuntimeClasspath
Look for multiple Selenium versions, manually copied JARs, or test/runtime configurations resolving different modules. Clean and rebuild after aligning versions. A package or class-loader mismatch can produce a cast failure even when class names appear correct, because Java treats classes loaded by different class loaders as different types.
Do not confuse a cast failure with an element-timing failure
Waiting changes when Selenium looks for an element; it does not add interfaces to the Java object. If the stack trace is a ClassCastException, fix the type or dependency problem first. If the error is NoSuchElementException, ElementNotInteractableException, or a stale-element error, synchronization may be the real issue.
Presence, visibility, and clickability are different
Selenium’s presenceOfElementLocated checks that an element is in the DOM; the API explicitly notes that this does not necessarily mean it is visible (ExpectedConditions Java API).
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement present = wait.until(
ExpectedConditions.presenceOfElementLocated(By.id("status")));
WebElement visible = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("search")));
WebElement clickable = wait.until(
ExpectedConditions.elementToBeClickable(By.id("submit")));
clickable.click();
Visibility means the element is displayed and has height and width greater than zero. Clickability requires visibility and enabled state. Choose the condition that matches the action instead of adding a longer arbitrary delay.
Rank #4
Use wait settings deliberately
Selenium’s Waiting Strategies documentation explains that page load completion does not guarantee that JavaScript-created or newly revealed elements are ready. It also cautions against mixing implicit and explicit waits without understanding the resulting timing behavior. Prefer a clearly configured explicit wait for the specific condition and keep implicit waiting disabled or intentionally documented.
WebDriver driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(Duration.ZERO);
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
Confirm the WebDriverWait constructor and Duration usage against your pinned Selenium version before copying this code into an older project.
A repeatable diagnostic workflow
- Capture the complete exception. Record the exact cast line, the fully qualified
Locatablename, and the runtime class named in the exception. - Check the import. Compare the imported interface with the API documentation for the Selenium dependency actually running the test.
- Print the runtime type. Use
getClass().getName()and inspect interfaces as shown above. - Trace wrappers and factories. Review page-object decorators, mocking frameworks, custom element factories, grid providers, and dependency-injection code.
- Remove unnecessary casts. Replace the variable with
WebElementand callclick(),sendKeys(),getText(), or another standard method. - Align dependencies. Make compile, test, and runtime classpaths resolve one compatible Selenium API family.
- Reclassify remaining failures. If the cast is gone but interaction fails, select a presence, visibility, or clickability wait and investigate stale references separately.
Common symptoms, causes, and fixes
| Symptom | Likely cause | Action |
|---|---|---|
WebElement cannot be cast to Locatable |
Runtime object does not implement the imported interface | Remove the cast or verify the concrete implementation before using Locatable. |
| Exception names an unexpected package | Import/API-version mismatch | Compare the import and resolved JAR with the version-specific Selenium API. |
| Runtime class is a proxy or decorator | Wrapper does not forward Locatable |
Use WebElement methods, unwrap through a documented API, or change the wrapper. |
| Cast succeeds, then click fails | Readiness or interactability problem, not casting | Use the appropriate explicit wait and check overlays, visibility, and enabled state. |
| Different behavior in tests and production | Different classpaths or class loaders | Compare dependency trees and remove duplicate/manual Selenium JARs. |
Code patterns to avoid
- Blind casting:
(Locatable) driver.findElement(locator)without checking whether location behavior is required. - Fixing timing with a cast: an explicit wait cannot make an unsupported object implement an interface.
- Changing imports by trial and error: an import is correct only when it belongs to the API version used at compile and runtime.
- Assuming every provider returns
RemoteWebElement: wrappers and custom implementations are validWebElementobjects without beingLocatable. - Mixing implicit and explicit waits casually: combined polling can make timeout behavior difficult to predict.
Or skip the browser setup
If your goal is to obtain a clean image or PDF of a page rather than drive Selenium interactions, ScreenshotNeo provides a website screenshot API and MCP server. A single request returns PNG, JPEG, WebP, or PDF. Cookie and consent banners are accepted and removed before capture, along with more than 60 known consent platforms, newsletter popups, and chat widgets. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemscURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
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)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the ScreenshotNeo documentation for authentication, output formats, and the 63 capture options. Its MCP server includes take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
Best Value
When to choose each repair
| Need | Recommended approach |
|---|---|
| Click, type, read, or inspect a DOM element | Keep the value as WebElement; remove the cast. |
| Element is missing or hidden | Use a presence or visibility wait, then interact through WebElement. |
| Element must be enabled before clicking | Use elementToBeClickable and investigate overlays. |
| Coordinate/location-specific API is unavoidable | Verify the runtime implementation, exact Locatable package, and dependency alignment. |
| Only a page image or PDF is required | Use a screenshot service such as ScreenshotNeo instead of maintaining browser automation. |
FAQ
Does waiting for an element make it Locatable?
No. Waiting affects lookup timing and state; it does not change the interfaces implemented by the returned Java object.
Can I safely cast every Selenium element to RemoteWebElement?
No. The cast assumes a particular implementation and can break with wrappers, proxies, custom providers, or future implementation changes. Depend on WebElement unless your code explicitly requires implementation-specific behavior.
What information should I include when asking for help?
Include the complete exception, cast line, Selenium version, fully qualified import, runtime class name, dependency tree, and whether a wrapper, mock, or remote-grid provider creates the element.
Recommended Free Tools
Frequently Asked Questions
Is Locatable required for normal Selenium clicks and typing?
No. The standard WebElement interface provides click(), sendKeys(), getText(), and related interaction methods.
Why does the same cast work on one test and fail on another?
The tests may receive different concrete implementations, wrappers, classpaths, or Selenium module versions.
The Bottom Line
Fix the error at its source: remove an unnecessary cast, or prove that the runtime element and Selenium dependencies implement the exact Locatable interface your code uses. Treat waits as synchronization tools, not type-conversion fixes.
Quick Recap
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.

