Playwright: page.goto: Timeout 30000ms exceeded
Last verified
TimeoutError: page.goto: Timeout 30000ms exceeded.
Call log:
- navigating to "https://example.com/", waiting until "load"What it means
The navigation started, but the page did not reach the requested load state before the navigation timeout. By default page.goto waits for load, which fires only after every image, stylesheet, script and iframe referenced by the page has finished. One slow third-party script, analytics beacon or ad iframe is enough to hold it open.
The last line of the call log tells you which state was awaited. If it says waiting until "load", the HTML probably arrived long ago and a sub-resource is the bottleneck. If the server never responded at all you will also see this error, so check the network tab of a trace.
What is not wrong: a timeout is not a DNS or connection failure; those fail immediately with net:: codes. And the page may be perfectly usable; you are simply waiting for the wrong signal.
What it looks like
// JavaScript
await page.route(/(analytics|doubleclick|hotjar)/, route => route.abort());
await page.goto('https://example.com/', { waitUntil: 'domcontentloaded' });
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
# Python
page.goto("https://example.com/", wait_until="domcontentloaded")
expect(page.get_by_role("heading", level=1)).to_be_visible()Why it happens
- waitUntil is load (the default) or networkidle and a third-party resource never finishes loading.
- The site streams or long-polls, so the network never goes idle.
- A bot-protection interstitial or challenge page holds the response.
- The server is genuinely slow or the job runs through a slow proxy.
- Resource-heavy pages on an underpowered CI machine.
How to fix it
- Open the trace (npx playwright show-trace) and check which requests were still pending at the timeout.
- Wait for less: page.goto(url, { waitUntil: 'domcontentloaded' }) or 'commit', then wait for the element you need with expect(locator).toBeVisible().
- Avoid networkidle; Playwright's docs discourage it for testing.
- Block heavy or irrelevant third-party requests with page.route() returning route.abort().
- Only then raise the limit with page.setDefaultNavigationTimeout() or the goto timeout option.
How to stop it recurring
Treat navigation as "the document arrived" and readiness as "the element I need is visible". Waiting on a concrete element is faster and more reliable than any load event. Keep third-party scripts out of automated runs where possible, and record traces on failure so slow requests are visible rather than guessed at.
Official documentation: playwright.dev/docs/api/class-page#page-goto. See all Playwright error messages.
Related errors
- page.goto: net::ERR_NAME_NOT_RESOLVEDError: page.goto: net::ERR_NAME_NOT_RESOLVED at https://exmaple.com/ Call log:…
- page.goto: net::ERR_CONNECTION_REFUSEDError: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/ Call…
- locator.click: Timeout 30000ms exceededTimeoutError: locator.click: Timeout 30000ms exceeded. Call log: - waiting…
Definitions
- PlaywrightPlaywright is Microsoft's open-source browser automation framework that provides a single API to control Chrom
- Chrome DevTools Protocol (CDP)The Chrome DevTools Protocol (CDP) is the JSON-over-WebSocket interface Chrome exposes for inspecting and cont
- CSS SelectorA CSS selector is a pattern used to identify and target specific HTML elements on a web page, widely used in b
- Headless ChromeHeadless Chrome is Google Chrome running without a visible window. It renders pages and runs JavaScript like n
- IframeAn iframe (inline frame) is an HTML element that embeds a separate web page within a parent page, creating an
- Web ElementA web element is any individual component rendered on a web page — buttons, links, input fields, images, text
Quick answers
What does "page.goto: Timeout 30000ms exceeded" mean in Playwright?
The navigation started, but the page did not reach the requested load state before the navigation timeout. By default page.goto waits for load , which fires only after every image, stylesheet, script and iframe referenced by the page has finished. One slow third-party script, analytics beacon or ad iframe is enough to hold it open. The last line of the call log tells you which state was awaited.
How do I fix "page.goto: Timeout 30000ms exceeded"?
1. Open the trace (npx playwright show-trace) and check which requests were still pending at the timeout. 2. Wait for less: page.goto(url, { waitUntil: 'domcontentloaded' }) or 'commit', then wait for the element you need with expect(locator).toBeVisible(). 3. Avoid networkidle; Playwright's docs discourage it for testing. 4. Block heavy or irrelevant third-party requests with page.route() returning route.abort(). 5. Only then raise the limit with page.setDefaultNavigationTimeout() or the goto timeout option.
Run browser automation you can watch and take over
Autonoly runs each job in a real cloud Chromium browser driven by Playwright. Timeouts and detached elements still happen; the difference is that you can watch the run live, see the step that failed, and take control of the browser to finish it.
Also see Live browser control.