How to Add Self-Healing to Selenium Tests
Add locator recovery to Selenium with Healenium-Web for Java or Healenium-Proxy for other supported languages, then review every healed result.
Direct answer: Selenium does not include self-healing locators as a built-in feature. One documented approach is Healenium-Web: for Java, start the Healenium backend, add its dependency, and wrap your WebDriver in SelfHealingDriver. For Java, Python, JavaScript, and C# clients, Healenium-Proxy sits between the client and Selenium server. Both approaches use successful runs as a locator baseline. When a locator later fails, healing may find a replacement and let the test continue.
A healed test is a signal to investigate, not proof that the intended behavior still works. Review the proposed locator, report, screenshot, and resulting application state. Disable healing where an element’s absence is the expected result.
1. Choose an integration path
| Approach | Best fit | Integration | Operational footprint |
|---|---|---|---|
| Healenium-Web | Java tests | Wrap the WebDriver in test code | Backend services |
| Healenium-Proxy | Java, Python, JavaScript, or C# Selenium clients | Point RemoteWebDriver at the proxy | Proxy and backend services, commonly alongside PostgreSQL and Selenium Grid |
Pick based on your language and how you want to operate the service stack. Proxy integration can suit mixed-language suites; Healenium-Web keeps the integration in Java test code. Check the vendor’s current installation documentation and your framework versions before adopting either path.
2. Set up Healenium-Web for Java
Start the backend and add the dependency
Follow the Healenium installation guide to start the backend and its required services. The following version was listed in the repository README reviewed for this guide; verify the current release and compatibility before pinning it.
<dependency>
<groupId>com.epam.healenium</groupId>
<artifactId>healenium-web</artifactId>
<version>3.5.8</version>
</dependency>
For Gradle, the corresponding dependency declaration is:
dependencies {
implementation 'com.epam.healenium:healenium-web:3.5.8'
}
Configure healing
Create src/test/resources/healenium.properties and set the backend addresses to match your installation. These example addresses match the documented local defaults.
recovery-tries = 1
score-cap = 0.5
heal-enabled = true
hlm.server.url = http://localhost:7878
hlm.imitator.url = http://localhost:8000
| Setting | What it controls | Practical note |
|---|---|---|
recovery-tries |
Number of healed locator candidates proposed | Start with the documented value of 1; review candidates before changing it. |
score-cap |
Minimum matching score for healing to proceed | The README’s example of 0.5 means a candidate needs at least a 50% match score. A permissive threshold can admit a wrong element. |
heal-enabled |
Global healing switch | Set false for runs where recovery is inappropriate. The README also documents the system property -Dheal-enabled=false. |
hlm.server.url |
Healenium backend address | Use the reachable backend URL from the test process. |
hlm.imitator.url |
Selector imitator service address | Use the reachable imitator URL from the test process. |
Wrap the normal WebDriver
Continue to use standard Selenium locator APIs after wrapping the driver. This example creates a browser session, wraps it, and quits it reliably. Replace the locator and assertion with those from your test framework and application.
import com.epam.healenium.SelfHealingDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class HealingExample {
public static void main(String[] args) {
WebDriver delegate = new ChromeDriver();
SelfHealingDriver driver = SelfHealingDriver.create(delegate);
try {
driver.get("https://example.com");
driver.findElement(By.cssSelector("[data-test='continue']")).click();
// Assert the expected application state here.
} finally {
driver.quit();
}
}
}
Use stable locators such as unique IDs or CSS selectors on stable test attributes when available. Keep the assertion about the user-visible outcome: a replacement locator finding some element does not establish that it is the correct one.
3. Set up Healenium-Proxy for other Selenium languages
Start the proxy stack using the proxy installation instructions. The docs show Docker Compose for a Selenium Grid setup and a local proxy endpoint at http://localhost:8085. Point your Selenium RemoteWebDriver at the proxy so it can forward commands to the Selenium server.
Python
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
proxy_url = "http://localhost:8085"
options = Options()
driver = webdriver.Remote(
command_executor=proxy_url,
options=options,
)
try:
driver.get("https://example.com")
driver.find_element("css selector", "[data-test='continue']").click()
# Assert the expected application state here.
finally:
driver.quit()
JavaScript
const { Builder, Browser } = require('selenium-webdriver');
(async () => {
const driver = await new Builder()
.forBrowser(Browser.CHROME)
.usingServer('http://localhost:8085')
.build();
try {
await driver.get('https://example.com');
const button = await driver.findElement({ css: "[data-test='continue']" });
await button.click();
// Assert the expected application state here.
} finally {
await driver.quit();
}
})();
The proxy documentation also provides JavaScript and Python examples and lists C# support. Keep the client, browser, Selenium server, proxy, and backend versions compatible; consult the current project examples for framework-specific setup.
4. Protect assertions from false recovery
Healing is useful when a locator broke because the page changed but the intended control still exists. It is risky when a missing element is the expected outcome: healing could locate a different element and change what the test observes. Healenium-Web documents disabling healing for a method with @DisableHealing.
import com.epam.healenium.annotation.DisableHealing;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
@DisableHealing
public boolean isContinueButtonPresent() {
try {
return driver.findElement(By.cssSelector("[data-test='continue']")).isDisplayed();
} catch (NoSuchElementException e) {
return false;
}
}
For proxy deployments, use the documented HEAL_ENABLED configuration to turn healing off where appropriate. The proxy docs list related environment variables including RECOVERY_TRIES, SCORE_CAP, SELENIUM_SERVER_URL, HEALENIUM_SERVER_URL, HEALENIUM_SERVICE, IMITATE_SERVICE, and HLM_LOG_LEVEL. Check the current docs for exact deployment values and defaults.
- Keep the original test assertion and add checks for the expected resulting state.
- Capture the original failure, healed locator, report, and screenshot.
- Review whether the candidate identifies the intended control, not merely a similar element.
- Promote a valid locator change into maintained test code and run the focused test repeatedly.
- Keep healing disabled in absence checks and other tests where a missing locator is meaningful.
5. Understand how healing works
Healenium’s documented flow saves locator information from a successful run. If a later lookup throws NoSuchElementException, it compares the current page state with the saved locator path, generates candidate locators, and can choose a high-scoring candidate so execution continues. Reports can include the healed locator and a screenshot.
This is a locator recovery mechanism. It does not establish that every test failure is repaired, nor that the application behavior is correct after recovery. It is tied to a prior successful baseline and a later lookup failure; unrelated failures still need ordinary diagnosis.
6. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| Backend connection warning or no session key | The backend URL is unreachable, its service is down, or the test uses the wrong host or port. | Check that the backend is running, then verify hlm.server.url and the corresponding proxy environment settings from the test container’s network context. |
| No healing occurs after a locator fails | There is no successful baseline for that locator, healing is disabled, the relevant service is unavailable, or the failure is outside the documented locator recovery flow. | Run the test successfully once to establish a baseline; confirm healing and service URLs; inspect the original exception and logs. |
| Test passes but selects the wrong control | A candidate locator matched a similar element or the threshold allowed a weak match. | Inspect the report and screenshot, assert the page state, tighten the locator or score threshold, and fix the maintained locator. Disable healing if absence is under test. |
| Report is missing or blank | Reporting or backend services may not have completed the report workflow, or versions/configuration may not match. | Check service health and logs, follow the current report setup documentation, and verify component compatibility. Do not treat a screenshot alone as proof the report was produced correctly. |
| Proxy session cannot start | The client is pointed at the wrong endpoint or the proxy cannot reach its Selenium server. | Use the proxy address as the RemoteWebDriver command executor and confirm SELENIUM_SERVER_URL is reachable from the proxy. |
| Repeated flaky failures remain | The issue may be timing, an overlay, stale state, or an application behavior change rather than a locator change. | Check the exact Selenium exception and the page at failure time. Wait for the condition the next action depends on; do not mask a race by accepting an arbitrary replacement. |
7. Performance, reliability, and operating cost
Healing adds a service interaction and state to the test workflow: successful runs establish reference data, and recovery may require the backend and selector service. The proxy route adds a network hop and more components to operate. The cited documentation does not provide an independently attributable latency or pass-rate benchmark, so measure the effect in your own suite rather than assuming healing makes tests faster or more reliable.
- Use a small, representative test subset for an initial rollout and inspect every healed result.
- Keep the backend, proxy, database, and Selenium service reachable from the right network boundary; container-local
localhostmay not mean the host machine. - Plan for service health, logs, persistent baseline data, and version compatibility as part of CI operations.
- Account for the infrastructure needed by the chosen deployment. The docs describe a stack that can include PostgreSQL, proxy, backend, selector imitator, and Selenium Grid.
- The reviewed sources provide no performance statistic for self-healing. Healenium advertises a commercial Pro offering, but check the vendor for current terms and feature availability.
8. Selenium practices that still matter
Self-healing should complement locator quality and explicit assertions. Selenium recommends verifying locators against the running application. Prefer unique, stable IDs or CSS selectors on stable attributes when available; avoid brittle absolute XPath and generated class names. Use waits for the actual condition required by the next step, and repeat a focused test to look for races. A passing rerun by itself does not prove a test is stable.
For broader Selenium practices, see the project’s guidance on using AI coding agents and locator recommendations.
Or skip the browser setup
If the task is to capture a page screenshot while investigating a UI change, ScreenshotNeo is a website screenshot API and MCP server for developers. It does not replace Selenium tests or locator healing. One GET request captures a URL as an image or PDF; see the ScreenshotNeo API 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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);
- Cookie banners are accepted and 60+ known consent platforms, newsletter popups, and chat widgets are removed before the capture; each step can be turned off.
- Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Responses include
X-Page-VerdictandX-Billedheaders. - An MCP server offers
take_screenshot,get_page_info, andcapture_pdftools for AI agents. - The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots.
Sign up free for 1,000 screenshots a month, with no card required.
FAQ
Does Selenium have self-healing built in?
No. The approach covered here adds Healenium-Web or routes Selenium through Healenium-Proxy.
Can healing fix any failing Selenium test?
No. The documented recovery flow addresses a missing element after a page change and depends on a prior successful baseline.
Should I accept every healed locator?
No. Review the candidate and verify the intended application state; update maintained test code when a replacement is correct.
Which integration supports Python and JavaScript?
The Healenium documentation lists Python and JavaScript support for its proxy integration. Healenium-Web is the Java in-process integration.


