Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
When Selenium raises StaleElementReferenceException, the WebElement you previously found no longer points to a usable element in the current page context. Keep the locator, wait for the page state you actually need, then locate the element again immediately before using it. If an update is expected to remove the old node, wait for EC.staleness_of(old_element) before finding its replacement.
What the exception means
Selenium identifies an element with a reference to a particular DOM node. That reference becomes stale when Selenium can no longer access the node in the current DOM. A variable holding the old WebElement does not automatically update to point to a replacement.
The exception can follow navigation or a page refresh, a JavaScript update that removes and recreates a node, or a change to an iframe context. A delay may hide a timing issue, but it does not repair an invalid reference. First establish whether the page or frame changed; then find the element in the correct context again. See Selenium’s stale-element troubleshooting guidance and its Python exception documentation for Selenium 4.49.0.
First check the page and browsing context
Before retrying, confirm that the browser is on the expected page and, if the target is inside a frame, that Selenium has switched into the frame currently containing it. A reference found before navigation, refresh, or a frame change may no longer apply. Fixing the context comes before waiting for the element.
#1 Best Overall
- After navigation or refresh, wait for a meaningful condition on the destination page and locate the target again.
- After a dynamic update, determine whether the target node was replaced or merely became hidden or disabled.
- For an iframe, switch to the intended current frame before locating the element inside it.
Use a locator-based explicit wait
Store the locator rather than carrying a WebElement across page updates. A locator-based expected condition can find the current matching element as the wait polls. The following Python example waits until a button is visible and enabled before clicking it:
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
submit_locator = (By.ID, "submit")
submit = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable(submit_locator)
)
submit.click()
element_to_be_clickable checks that the located element is visible and enabled. If you need only to confirm that an element exists in the DOM, use presence_of_element_located; for an element that must be visible, use visibility_of_element_located. Choose the condition that represents the state your next action requires rather than adding a fixed sleep. Selenium documents these Python conditions in Waiting with Expected Conditions.
A wait checks its condition when it polls; the page can still change after the condition succeeds. Keep the locate-and-act sequence close together. If the application can replace the target in that interval, handle that specific transition instead of assuming the wait eliminates every race.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #2
Wait for the old element to go stale when replacement is expected
If a known action replaces a row, card, or other node, waiting for the old element to become detached can make the transition explicit. Then locate the replacement with the original locator:
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
row_locator = (By.CSS_SELECTOR, "tr.selected")
old_row = driver.find_element(*row_locator)
# Trigger the action that replaces the row here.
WebDriverWait(driver, 10).until(EC.staleness_of(old_row))
new_row = WebDriverWait(driver, 10).until(
EC.presence_of_element_located(row_locator)
)
staleness_of waits until the old reference is no longer attached to the DOM. It does not revive that object or return the replacement; the final wait performs a fresh lookup. If the application updates the existing node rather than replacing it, staleness may never occur, so wait instead for the relevant changed content, visibility, or other application-specific state.
Retry only when repeating the action is safe
A narrow retry can help when a brief DOM replacement occurs between locating and using an element. Keep the locator, catch only StaleElementReferenceException, relocate the intended element, and retry only an operation that is safe to repeat. Selenium’s troubleshooting guidance describes this reacquire-and-retry approach.
Rank #3
from selenium.common.exceptions import StaleElementReferenceException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
save_locator = (By.ID, "save")
for attempt in range(2):
button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable(save_locator)
)
try:
button.click()
break
except StaleElementReferenceException:
if attempt == 1:
raise
This is a bounded retry: it does not loop forever or discard the final error. Use it only if clicking again cannot duplicate a consequential action. For a form submission, payment, deletion, or other side effect, first determine whether the first attempt took effect; blindly repeating it may be incorrect even if the click raised an exception. If the locator now matches a different element, stop and correct the page state or locator rather than retrying.
Free tools Windows power users keep installed
One-click scans. No signup required.
Choose the fix that matches the change
| What changed | What to wait for | What to do next |
|---|---|---|
| Navigation or refresh | A meaningful condition on the destination page | Locate the target again in the new page context. |
| A dynamic update replaced a node | staleness_of(old_element) if detachment is the expected event |
Find the replacement with its locator. |
| The current element must become usable | Visibility or clickability using a locator | Act promptly on the newly located element. |
| The frame or browsing context changed | The correct page and frame state | Switch to the intended current context, then locate again. |
These patterns follow Selenium’s descriptions of stale references and expected conditions. The essential distinction is whether you are waiting for a usable current element, for the old one to disappear, or for the correct browsing context.
Troubleshoot common failures
The same exception returns after adding a sleep
A fixed pause neither proves the target is ready nor ensures it remains unchanged. Replace it with a wait for the needed state using a locator. If node replacement is part of the update, wait for staleness and then locate the new node.
Rank #4
The wait times out
Check that the locator matches the current page, that the browser is in the right frame, and that the chosen condition can become true. For example, a clickability wait will not succeed if the element remains disabled or hidden. If the application keeps an existing node and changes its contents, waiting for staleness is the wrong condition.
The replacement lookup finds the wrong element
Reassess whether the locator uniquely identifies the intended target in the updated page. If multiple elements match, refine the locator or scope it to the correct container; do not treat a successful lookup as proof that it is the right element.
Recommended Free Tools
A retry makes the problem worse
Remove broad catch-and-ignore logic and any unbounded retry loop. Confirm whether the operation is safe to repeat, preserve the last exception, and inspect whether navigation, a DOM update, or a context change explains the stale reference. Retrying cannot correct a wrong locator or wrong page state.
Best Value
Performance and reliability considerations
Explicit waits poll for a condition instead of sleeping for an assumed duration. This lets the script continue when the required state is observed and wait longer when it is not yet ready, up to the timeout you set. The example uses a 10-second timeout as a code choice, not a universal Selenium requirement; choose a limit suitable for your application and fail clearly if the condition never occurs.
Reliability comes from waiting for the state that matters and re-locating at the point of use. Avoid retaining element objects across operations that can replace page nodes. Do not catch every exception as if it were transient: a stale reference, a missing element, a timeout, and a wrong frame indicate different conditions and need different fixes.
Or skip the browser setup
If your goal is a screenshot rather than browser interaction, ScreenshotNeo can return a website capture through one GET request. Its clean-shot process accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify the page verdict and billing status in headers. It also provides an MCP server for AI agents, with take_screenshot, get_page_info, and capture_pdf tools.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Example using cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Use the ScreenshotNeo documentation for API options and setup. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month, with no card.
FAQ
Does a stale element mean Selenium lost the whole page?
No. It means the particular element reference can no longer be used in the current DOM or page context. Other elements may remain accessible, but confirm the correct page and frame before continuing.
Can I reuse a stale WebElement after waiting?
No. A wait can detect a state change, but the old reference does not become current again. Locate the element again.
Is there a published frequency for this exception?
The cited Selenium documentation explains the exception and its causes but does not provide a prevalence statistic.
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.

