The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →For current Playwright code, use page.waitForURL() when an action should change the main page’s URL; in Playwright Test, await expect(page).toHaveURL(...) often states the expected result more clearly. Use page.goto() when you already know the destination. Avoid the deprecated page.waitForNavigation(): Playwright calls it inherently racy and recommends page.waitForURL() instead.
Choose the right kind of navigation wait
| Situation | Use | What it establishes |
|---|---|---|
| Open a known URL directly | page.goto(url) |
Starts an explicit navigation and can wait for a selected document lifecycle event. |
| A click or form submission should change the main page URL | page.waitForURL(pattern), or a Playwright Test URL assertion |
Waits for or asserts the expected URL outcome. |
| A child frame should navigate | frame.waitForURL(pattern) |
Waits for the specified frame’s URL. |
| The page must be usable after navigation | Assert the URL and the relevant visible or otherwise user-observable state | Checks the condition the test actually depends on, rather than assuming a network event proves readiness. |
Playwright’s actions and web-first assertions already wait for their conditions. Add a separate wait only when it represents an outcome your test needs to observe. See the Writing tests guide and Pages guide.
Wait for a URL change caused by an action
Separate wait promise
Start waiting before triggering the action. This prevents a quick URL change from happening before the wait is listening.
const urlPromise = page.waitForURL('**/target.html');
await page.getByRole('link', { name: 'Continue' }).click();
await urlPromise;
A string containing a wildcard is a URL pattern. Without wildcard characters, a string passed to waitForURL() is an exact URL match. The method also accepts a regular expression, URL pattern, or predicate. Make the match specific enough that an unrelated route cannot satisfy it. See the Page API reference.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
Assert the result in Playwright Test
When the test is checking the destination rather than coordinating a separate event promise, a web-first assertion is often simpler:
await page.getByRole('link', { name: 'Continue' }).click();
await expect(page).toHaveURL('**/target.html');
The assertion retries while waiting for the expected URL, so an extra fixed delay is unnecessary. The Writing tests guide documents URL assertions and Playwright’s automatic waiting.
Navigate directly to a known URL
Use page.goto() for explicit navigation, such as setting up a test at its starting page:
await page.goto('https://example.com');
By default, goto() waits for the load lifecycle state. Its waitUntil option can select commit, domcontentloaded, or load. Choose a lifecycle point that suits the page and then assert the application state needed by the test; reaching a lifecycle event alone does not prove that a particular interface element is ready. The available options are documented in the Page API reference.
Rank #2
Wait for the main frame or a child frame
page.waitForURL() applies to the main page. If the URL change belongs to a particular frame, use that frame’s URL wait instead:
const frame = page.frame({ name: 'account-frame' });
if (!frame) throw new Error('Account frame was not found');
const urlPromise = frame.waitForURL('**/signed-in');
await page.getByRole('button', { name: 'Continue in frame' }).click();
await urlPromise;
Replace the frame lookup and action with the ones in your page. The explicit null check prevents a missing frame from becoming a less informative error. The corresponding frame API is documented in the Frame API reference; it also deprecates frame.waitForNavigation() in favor of frame.waitForURL().
Why new code should not use page.waitForNavigation()
page.waitForNavigation() waited for main-frame navigation and returned the main resource response. But URL changes do not always map neatly to a new document response: History API changes count as navigation, while anchor or History API navigation can resolve with null; redirects resolve with the final non-redirect response. Playwright’s Page API marks the method deprecated and says: “This method is inherently racy, please use page.waitForURL() instead.” Use a URL wait or a web-first assertion to express the expected destination. The same migration applies to frame.waitForNavigation().
The docs identify page.waitForURL() as added in v1.11, but do not establish the release in which waitForNavigation() was deprecated. See the current Page API reference and Frame API reference.
URL reached is not the same as application ready
A URL wait answers whether the browser reached a matching URL. A lifecycle event answers whether a document reached a browser-defined loading milestone. Neither necessarily proves that the specific control, data, or state your test needs is ready.
- Assert the expected URL when the route itself matters.
- Assert a user-visible element or other application state when that is what the next test step depends on.
- Do not use
networkidleas a general readiness signal. Playwright documents it as discouraged for testing; ongoing requests can continue after the relevant interface is ready, and network silence does not prove that the desired UI appeared. - Avoid
waitForTimeout()as a synchronization strategy in production tests. Timer-based waits are discouraged because they can make tests flaky.
Use web assertions that describe the condition, not an arbitrary pause or network condition. The cautions are in the Page API reference.
Set a navigation timeout when the environment needs it
Navigation methods, including goto() and waitForURL(), are affected by the default navigation timeout. Set one for the test configuration when navigations in that environment predictably need more time:
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
navigationTimeout: 30_000,
},
});
Or provide a timeout for a particular explicit navigation:
Recommended Free Tools
Rank #4
await page.goto('https://example.com', { timeout: 30_000 });
page.setDefaultNavigationTimeout() applies to navigation methods including goto(), reload(), goBack(), goForward(), setContent(), waitForNavigation(), and waitForURL(); it takes priority over general default-timeout settings. A longer timeout can accommodate a genuinely slow environment, but it cannot fix a wrong URL pattern or an unsuitable readiness condition. See Timeouts and the Page API reference.
Troubleshoot navigation waits
The wait times out although the click succeeded
- Check the actual resulting URL and make the glob, regular expression, or predicate match that destination. A literal string without wildcards is an exact match.
- Confirm that the action changes the main page URL. If only a child frame changes URL, wait on that frame.
- If the action changes visible application state without changing the URL, assert that state instead of waiting for navigation.
- Check whether the navigation genuinely takes longer than the configured timeout before increasing it.
The test sometimes misses the navigation
If using a separate waitForURL() promise, create it before the click or other trigger, then await the action and the promise. If you only need to verify the result in Playwright Test, prefer toHaveURL(), which waits for its assertion condition.
The URL matches but the next step still fails
Add a web-first assertion for the exact element or application state required next. Do not assume that URL matching or networkidle means the page is ready for that interaction.
A wait on the old method returns no response
Anchor and History API navigation can resolve waitForNavigation() with null. Migrate to waitForURL() when the URL outcome matters, or assert the relevant page state when that is the requirement.
Or skip the browser setup
If your goal is to capture a page image or PDF rather than test a navigation, ScreenshotNeo can return a screenshot or PDF with one GET request. Its cookie-banner handling and cleanup are separate from Playwright’s test navigation waits.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
See the ScreenshotNeo API documentation for request options. It can accept cookie or consent banners and remove known consent platforms, newsletter popups, and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Its MCP server provides screenshot tools for AI agents, and the free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up for ScreenshotNeo free: 1,000 screenshots a month, no card.
Frequently Asked Questions
Does page.waitForURL() wait for the page’s content to finish loading?
It waits for the URL to match; use a separate assertion for the page state your test needs.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchCan page.waitForURL() match only part of a URL?
Yes. Use a glob, regular expression, URL pattern, or predicate; an exact string without wildcards matches the full URL.
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.




