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

A successful click only confirms that the browser performed an input action; it does not prove that the expected page or application state finished loading. Fix “click succeeded but load failed” by identifying what the click should do, waiting for that specific outcome, and checking the URL, page state, and network response separately. In Playwright, use an explicit URL or event wait when needed; in Selenium, wait for the destination URL or a stable element rather than assuming the click itself waited for navigation.

What “click succeeded but load failed” means

Browser automation has several separate stages: locating and activating a control, receiving any resulting navigation or popup, loading document resources, and rendering the application state your test needs. A click can succeed at the first stage while a later stage times out, goes to an unexpected URL, or never occurs.

The wording alone does not identify a single failure. It may refer to a navigation wait timing out, a destination page failing to become usable, or an application changing state without a full page load. Start by determining which outcome the test expects; do not treat every post-click delay as a page-load problem.

Identify the outcome before changing timeouts

Record the current URL, perform the click, and then determine what should have happened. The wait depends on that outcome:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • URL change: wait for the expected destination URL, not merely for generic page loading.
  • Popup or new tab: wait for the new page or popup event, then assert its URL or content.
  • Download: wait for the download event rather than navigation.
  • Single-page application update: wait for the new view’s stable element or a documented application-ready signal.
  • API-driven result: wait for the relevant response or rendered result, depending on what the test needs to verify.

Register event waits before the click when an event might happen immediately. If the click has already completed, an event-only wait can miss the event and time out even though the browser acted correctly.

Fix it in Playwright

Wait for the destination URL

Playwright waits for navigations initiated by actions such as a click, but an explicit URL wait is useful when the destination is part of the test or the click can lead to more than one destination. The navigation guide documents waiting for the expected URL; the page API describes navigation lifecycle options and timeouts.

import { test, expect } from '@playwright/test';

test('sign-in link opens the login page', async ({ page }) => {
  await page.goto('https://example.com');
  const before = page.url();

  await page.getByText('Click me').click();
  await page.waitForURL('**/login');

  expect(page.url()).not.toBe(before);
  await expect(page.getByRole('heading', { name: 'Log in' })).toBeVisible();
});

Replace the example URL, link text, path, and heading with values from your application. The final assertion checks the usable destination, not just that some navigation occurred. If the link can open a popup, use a popup wait rather than treating the original page’s URL as the outcome.

Documentation: Playwright navigation and waiting and Playwright Page API.

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

Choose a lifecycle milestone that matches the test

When using a navigation wait, Playwright supports milestones including commit, domcontentloaded, and load. These represent different stages: a response has committed, the document’s initial HTML has been parsed, or the load event has fired. A test that needs only an initial element may not need to wait for every resource associated with load. Conversely, reaching an early milestone does not prove that the application is ready for the next interaction.

Use the narrowest milestone that satisfies the test, then assert the page-specific condition you actually need. Avoid adding a generic delay as a substitute for a stable condition.

Separate action and navigation timeouts

Playwright exposes configurable action and navigation timeouts. Before increasing either, determine which wait is expiring and what event it expects. If the expected URL is wrong or the app never emits the expected response, a larger timeout only delays the same failure. If the condition is correct but the operation genuinely takes longer in your environment, adjust the relevant timeout rather than changing unrelated waits.

Fix it in Selenium

Wait explicitly after clicking

Selenium’s URL-navigation commands use page-load strategies tied to document.readyState. A click that triggers navigation is not governed by the same URL-navigation wait in the same way. After the click, use an explicit wait for the destination URL or an element that proves the destination is ready. Selenium’s wait documentation covers explicit waits and expected conditions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

 driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    old_url = driver.current_url

    driver.find_element(By.LINK_TEXT, "Click me").click()
    wait = WebDriverWait(driver, 15)
    wait.until(EC.url_contains("/login"))
    wait.until(EC.visibility_of_element_located(
        (By.CSS_SELECTOR, "h1.login-title")
    ))

    assert driver.current_url != old_url
finally:
    driver.quit()

Remove the leading space before driver = webdriver.Chrome() if your editor copied it as part of the code block; the runnable form is unindented at top level. Change the locator, URL fragment, selector, and timeout to match the application. A URL condition is useful for navigation; the element condition confirms that the view the test needs is visible.

Documentation: Selenium waits and Selenium driver options.

Understand Selenium page-load strategies

Selenium exposes normal, eager, and none page-load strategies. They offer different readiness guarantees for URL navigation and affect when WebDriver returns from navigation commands. They are not a replacement for waiting on the result of a click: if your test needs a particular destination or control, assert that condition explicitly. Changing the strategy also does not make an application-specific asynchronous update complete.

Account for single-page apps and hydration

In a single-page application, a click may update the view without changing the URL or reloading the document. In that case, a navigation wait is the wrong signal. Wait for an element unique to the new view, a state change, or the application’s documented ready signal.

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

There is a related early-interaction failure: a page can render a control before its JavaScript event listeners are attached. Playwright warns that a click during this hydration gap can be ignored even though the control appears on screen. Prefer fixing the application’s hydration/readiness behavior or waiting on an explicit ready condition; adding a blind sleep is less reliable because the delay may be too short in one run and wasteful in another.

Selenium also notes that readyState reflects HTML asset loading but does not account for every later JavaScript change. A document reporting ready does not necessarily mean an SPA has finished rendering the view your test is checking.

Diagnose the failure in a repeatable order

  1. Log the starting URL. Record the URL immediately before the action.
  2. Identify the expected result. Decide whether this is navigation, a popup, a download, an in-page transition, or an API-driven change.
  3. Set up the correct wait. Register an event wait before clicking if the event may occur immediately; otherwise wait for a destination URL or stable state after the action.
  4. Check what actually happened. Log the URL immediately after the click and compare it with the expected destination. Assert the destination element or state, not just the absence of an exception.
  5. Inspect lifecycle and network evidence. Determine whether navigation committed and whether requests failed. Check the HTTP status separately: a 404 or 503 is an HTTP response, not necessarily a failed network request.
  6. For an SPA, inspect app readiness. Confirm that the new view or ready signal appeared and that event handlers were attached before the next interaction.
  7. Adjust timeouts or strategy last. Once the expected event is clear, tune the relevant Playwright timeout or Selenium page-load strategy to fit the actual operation.

Distinguish a failed request from an HTTP error page

Playwright classifies 404 and 503 responses as successful HTTP responses at the request layer; they do not appear as requestfailed solely because of those status codes. A page can therefore load an error response without a network-failure event. If the test must reject error pages, assert the response status or expected page content separately from monitoring failed requests.

Conversely, a request failure points to a network-level problem rather than simply an unwanted HTTP status. Keep these checks separate so the test reports whether a request failed, an error status was returned, or the expected UI never appeared.

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

Documentation: Playwright BrowserContext API.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common errors and fixes

Symptom Likely cause Fix
Click returns, then a navigation wait times out The click did not navigate, or it reached a different URL than expected. Check the post-click URL and wait for the actual outcome, such as an SPA element or popup.
Wait for load times out, but the page is usable The test waits for a later lifecycle milestone than it needs. Use an appropriate earlier milestone and assert the required destination element.
URL changes but the next action fails Navigation occurred, but the target view or control is not ready. Wait for the stable destination element or application-ready signal.
Visible control ignores the click In a hydrated application, the control may render before its event listeners are attached. Wait for app readiness or correct the hydration timing before interacting.
No request-failure event appears, but an error page is shown The server returned an HTTP error status such as 404 or 503. Assert the response status or error-page content separately from request failures.
A longer timeout does not help The expected URL, event, or state may never occur. Verify the expected outcome and inspect navigation and network evidence before changing the timeout.

Performance and reliability trade-offs

Waiting for the exact outcome usually makes a test both faster and more diagnostic than waiting for an arbitrary fixed delay. A wait for a stable element can finish as soon as that element appears, while a generic late-stage load condition may hold the test for resources that are irrelevant to its assertion. The trade-off is that the condition must genuinely indicate readiness; an element that appears before it can respond to input is not sufficient.

Use timeouts as failure bounds, not as readiness definitions. Keep separate waits for navigation, action completion, and application state when those are different requirements. This makes a failure point to the stage that did not complete instead of reporting only that a broad “page load” deadline expired.

Or skip the browser setup

If the immediate goal is to save a page image or PDF rather than automate an interactive browser journey, ScreenshotNeo can return a capture from one GET request. That is a different task from fixing a click or proving a navigation, but it can be useful for obtaining a page artifact without managing browser setup. 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
  • Cookie banners, popups, and chat widgets are removed before the shot; each cleanup step can be turned off.
  • Bot checks, blank pages, and failed loads are not billed; response headers identify the page verdict and billing status.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents.
  • The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots.

Sign up for ScreenshotNeo’s free plan.

Frequently Asked Questions

Does a successful click prove that the destination page loaded?

No. It confirms the input action, not that a particular navigation or application state completed.

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

Should I always wait for the browser’s load event after clicking?

No. Choose a lifecycle milestone or state condition that matches what the test needs to verify.

Can a 404 or 503 explain why no request-failure event was recorded?

Yes. Playwright treats those as HTTP responses; check response status separately from network request failures.

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.