Next-Gen App & Browser Testing Cloud
Trusted by 2 Mn+ QAs & Devs to accelerate their release cycles

On This Page
Playwright timeouts control how long actions, navigation, and assertions wait before failing. Adjust settings to prevent flaky tests and keep automation reliable.

Inimfon Willie
January 11, 2026
Handling Playwright timeouts is crucial to ensure tests run reliably and do not fail due to slow-loading pages or elements. It helps identify real issues instead of false negatives caused by temporary delays. Proper timeout management improves test stability, making automation more predictable. Additionally, it allows customization for different scenarios, balancing speed with accuracy in testing workflows.
Playwright uses timeouts to control how long it should wait for actions, events, or conditions before throwing an error. They help ensure tests fail quickly when something goes wrong rather than hanging indefinitely.
Types of Timeouts in Playwright
How to Configure Playwright Timeouts
You can configure timeouts in Playwright globally or at a more granular level.
For example, set a default timeout for all actions with page.setDefaultTimeout(), or adjust navigation-specific waits with page.setDefaultNavigationTimeout().
Example: page.setDefaultTimeout(5000) // sets 5 seconds for actions
In Playwright, a timeout is the maximum amount of time the framework (Playwright) will wait for a particular action or event to complete before it considers the operation failed and throws an error.
For example, when testing a login form, after submitting the user credentials, Playwright waits for the authentication response or a specific element, like a dashboard or welcome message, to appear.
If the server takes too long to respond and the expected element doesn’t show up within the set timeout, Playwright throws a timeout error.
Timeouts are what separate flaky tests from reliable ones. They help your automation handle real-world delays whether that’s a slow network, a delayed DOM update, or an API that takes a few seconds too long to respond.
Prevent Hanging Test Runs
Without timeouts, a test might keep waiting if something goes wrong. Maybe an API fails, the test runner just waits. It also takes time, consumes memory, and never ends.
Playwright overcome this with built-in default timeouts for tests, actions, and assertions. These ensure that tests automatically fail after the default time elapses, even if you didn’t set a specific timeout.
Example:
await expect(page.getByRole('button', {name:'Checkout'}))
.toBeVisible({timeout: 10000});
If the button doesn’t show up within 10 seconds, the test fails immediately. If you don’t specify a timeout, Playwright uses its default value, so there are no infinite waits or wasted resources.
Handle Slow Loading Components
Not all slowness is a bug. Some components like animated dropdowns or sections powered by external APIs take longer to appear. A test that assumes instant visibility often fails for the wrong reasons.
Timeouts give elements room to load, failing only when they truly don’t show up.
Example:
await expect(page.locator('#mz-product-tab-37217979-0'))
.toBeVisible({timeout: 15000});
Here, the test allows up to 15 seconds for the element to become visible. This protects your test from false failures caused by normal delays, while still failing fast if something genuinely breaks.
Faster Feedback on Failures
No one should wait five minutes to discover that a login flow is broken. Proper timeouts give you faster feedback when something goes wrong.
Example:
await expect(page.locator('.dashboard'))
.toBeVisible({timeout: 8000});
The test waits up to 8 seconds for the dashboard to load. If it doesn’t appear, that’s likely a real issue: slow authentication, blocked API calls, or database lag.
Instead of long waits, you get quick, actionable feedback.
Note: Run your Playwright timeout tests across 50+ real browsers. Try TestMu AI Today!
Timeouts in Playwright control how long things are allowed to wait. Some wait for pages to load. Others wait for elements to show up or actions to complete.
Here are the main types of timeouts in Playwright:
It is the top-level timeout. It sets the maximum time for the entire test run. If this is hit, all tests are stopped immediately, no matter what their individual timeouts are.
Example:
import { defineConfig } from '@playwright/test';
// playwright.config.ts
export default defineConfig({
globalTimeout: 60*60*1000, // 1 hour
});
It sets the maximum time a single test (including hooks and fixtures) can run.
Global test timeout in config:
export default defineConfig({
timeout: 30*1000, // 30 seconds per test
});
Per-test timeout:
test('slow test', async () => {
test.setTimeout(60*1000); // 1 minute for this test only
});
It controls how long beforeAll, afterAll, beforeEach, and afterEach hooks can run.
Example:
test.describe('Product Management', () => {
test.beforeEach(async ({ page, database }) => {
testInfo.setTimeout(20000); // 20s
await database.cleanupTestData();
await page.goto('/admin/products');
await expect(page.locator('[data-testid="products-table"]')).toBeVisible();
});
test.afterEach(async ({ page }) => {
testInfo.setTimeout(10000); // 10s
if (test.info().status === 'failed') {
await page.screenshot({
path: `test-results/failure-${test.info().title.replace(/s/g, '-')}.png`,
fullPage: true,
});
}
});
});
It controls how long a fixture’s setup can take. If setup inside use() exceeds the timeout, the test fails.
Example with custom fixtures:
// Define fixture type
type UserFixture = {
username: string;
password: string;
};
// Extend base test
const test = base.extend<UserFixture>({
username: [async ({}, use) => {
const username = 'testuser';
await use(username);
}, { timeout: 30_000 }],
password: [async ({}, use) => {
const password = 'testpass123';
await use(password);
}, { timeout: 30_000 }],
});
Here, both fixtures have a 30-second setup timeout.
It sets the maximum time for user actions like click(), fill(), or check().
Global config:
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
actionTimeout: 60*1000, // 1 minute
},
});
Per-action timeout:
await page.getByRole('link', { name: 'My Account' })
.click({ timeout: 10000 });
Here, the click waits up to 10 seconds. Other actions follow the global/test timeout.
It controls how long Playwright retries expect() assertions before failing.
Global config:
import { defineConfig } from '@playwright/test';
export default defineConfig({
expect: {
timeout: 10000, // 10 seconds
},
});
Per-assertion override:
await expect(page.locator('h1'))
.toHaveText('My Account', { timeout: 10000 });
In automation testing with Playwright, validating timeout scenarios is essential for building resilient test scripts that mirror real user behavior.
Progress bars often trigger timeout issues in tests. They appear during uploads, submissions, or background processing, and tests must wait until they complete.
This demonstration covers three strategies:
All examples use the Jquery Download Progress-Bar Demo of TestMu AI Selenium Playground.
Make sure you have the following installed before starting:
Project Structure
Organize your project like this for clarity and maintainability:
playwright-timeout/
├── tests/
│ ├── progress-bar.spec.ts
│ ├── dynamic-content.spec.ts
│ ├── hover-interactions.spec.ts
│ └── network-conditions.spec.ts
├── lambdatest-setup.ts
├── playwright.config.ts
├── package.json
└── .env
This test shows what happens when you set an unrealistic timeout. The progress bar never finishes in the given 1000ms, so the test fails as expected.
test('demonstrates timeout failure with insufficient wait time', async ({ page }) => {
await page.click('#downloadButton');
// Intentionally fails to show poor timeout handling
await expect(async () => {
await expect(page.locator('.progress-label'))
.toHaveText('Complete!', { timeout: 1000 });
}).rejects.toThrow(/Timed out/);
console.log("Timeout failure successfully demonstrated");
});

This test uses staged timeouts to handle delayed UI updates without false positives.
test('handles progress completion with proper timeout strategy', async ({ page }) => {
const startTime = Date.now();
await page.click('#downloadButton');
// Step 1: Wait for progress bar to appear
await expect(page.locator('#progressbar')).toBeVisible({ timeout: 10000 });
console.log('Progress bar appeared, waiting for completion...');
// Step 2: Wait for completion with extended timeout
await expect(page.locator('.progress-label'))
.toHaveText('Complete!', { timeout: 30000 });
const duration = Date.now() - startTime;
console.log(`Progress completed in ${duration}ms`);
// Step 3: Final verification
await expect(page.locator('.progress-label')).toHaveText('Complete!');
});
Some UIs are inconsistent, so retries can help stabilize test runs.
test.describe.configure({ retries: 2 });
test.describe("Retry: Progress Bar Flake Handler", () => {
const PROGRESS_URL =
"https://www.lambdatest.com/selenium-playground/jquery-download-progress-bar-demo";
test.beforeEach(async ({ page }) => {
await page.goto(PROGRESS_URL, {
waitUntil: "domcontentloaded",
timeout: 60000,
});
});
test("implements retry mechanism for unreliable progress bars", async ({ page }, testInfo) => {
if (testInfo.retry > 0) {
console.log(`Retrying test (Attempt #${testInfo.retry})`);
await page.reload({ waitUntil: "domcontentloaded" });
}
await page.click("#downloadButton");
await expect(page.locator(".progress-label")).toHaveText("Complete!", {
timeout: 30000,
});
console.log("Progress completed successfully");
});
});
Test Execution:
Run the test on using the below command:
npx playwright test tests/progress-bar.spec.ts --project=local-chrome
This command produces terminal output and an HTML report for detailed results.

Once your tests run locally, you can scale them to the cloud using TestMu AI. Running on TestMu AI Playwright automation cloud lets you validate Playwright timeout across multiple browsers, operating systems, and real-world network conditions.
The only difference is that your configuration must include TestMu AI Username and Access Key and Playwright automation capabilities so tests can run in the cloud. To get started, check out this guide on Playwright testing with TestMu AI.
To get your TestMu AI credentials, go to Account Settings, then click on Password & Security. You can generate capabilities from the TestMu AI Automation Capabilities Generator.
To run tests on the TestMu AI platform, you can follow the steps below:
Step 1: Create a .env file in your project root:
LT_USERNAME=your-username
LT_ACCESS_KEY=your-access-key
Step 2: Update the playwright.config.ts file by importing dotenv and load env vars:
import dotenv from 'dotenv';
import path from 'path';
dotenv.config({ path: path.resolve(__dirname, '.env') });
const LT_USERNAME = process.env.LT_USERNAME;
const LT_ACCESS_KEY = process.env.LT_ACCESS_KEY;
if (!LT_USERNAME || !LT_ACCESS_KEY) {
console.error('Error: LambdaTest credentials not found.');
process.exit(1);
}
Now modify the playwright.config.ts file for running tests on TestMu AI:
export default defineConfig({
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
use: {
baseURL: 'https://www.lambdatest.com/selenium-playground',
trace: 'on-first-retry',
},
projects: [
{ name: "chrome:latest:macOS Sonoma@lambdatest" },
{ name: "pw-firefox:latest:macOS Sonoma@lambdatest" },
{ name: "pw-webkit:latest:macOS Sonoma@lambdatest" },
],
});
Step 3: Add the lambdatest-setup.ts file and define capabilities for different conditions:
export const baseCapabilities = {
browserName: "Chrome",
browserVersion: "latest",
"LT:Options": {
platform: "Windows 11",
build: "Playwright Sample Build",
name: "Playwright Sample Test",
user: process.env.LT_USERNAME,
accessKey: process.env.LT_ACCESS_KEY,
video: true,
console: true,
resolution: "1920x1080",
visual: true,
},
};
Test Execution:
Run the below command to execute the test:
npx playwright test tests/progress-bar.spec.ts

Timeouts let you control how long Playwright waits before failing. You can adjust them globally, per test, per action, or even per environment, depending on your needs.
Change Global Timeout
If you want a timeout that applies to all tests, set globalTimeout in your playwright.config.ts file:
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
globalTimeout: 6 * 1000, // 6 seconds
});
Any test that runs longer than 6 seconds will fail automatically.
Change Timeout for a Single Test
If one of your tests takes longer (like login, checkout, or file upload), increase the limit using the test.setTimeout():
test('user registration', async ({ page }) => {
test.setTimeout(30000); // 30 seconds
// test steps...
});
This way, you only extend the timeout for this test, not the whole suite.
Change Timeout for an Action
If one specific step takes longer (like a payment or API-heavy workflow), override the timeout just for that action:
// Normal clicks use default timeout
await page.click('text=Reviews');
// Give the payment step extra time
await page.click('button:has-text("Pay Now")', { timeout: 45000 });
You don’t slow down other actions, just the one that needs more time.
Change Timeout for an Assertion
If you’re waiting for a page change or element to appear, set a custom timeout on the assertion:
// Allow 20s for redirect
await expect(page).toHaveURL(/.*account/success/, { timeout: 20000 });
// Allow 15s for success message
await expect(page.locator('h1')).toBeVisible({ timeout: 15000 });
Each check gets the time it really needs, nothing more.
Change Timeouts Per Environment
You can also give different environments their own timeout rules inside your config:
projects: [
{ name: 'local-dev', use: { actionTimeout: 5000, navigationTimeout: 10000 } },
{ name: 'staging', use: { actionTimeout: 10000, navigationTimeout: 20000 } },
{ name: 'production',use: { actionTimeout: 20000, navigationTimeout: 45000 } }
]
This way, your tests behave realistically whether you’re running locally, in staging, or in production.
Timeouts can make tests fail if elements or responses take longer than expected. Following these practices will keep your playwright test stable, fast, and less prone to errors.
Your test may occasionally take longer than anticipated when using Playwright, which could result in timeout problems. Fixes for these issues vary depending on their kind. These are the typical ones, along with their go-to solutions.
To resolve, check your URL first; it might be wrong. Then, you can increase your timeout for that specific navigation, for example, use page.goto(‘https://www.example.com’, {timeout: 60000}) or set global ones with page.setDefaultNavigationTimeout(60000).
For single-page apps, use page.waitForLoadState(‘domcontentloaded’) instead of the default ‘load’ to avoid waiting for images or other heavy media files.
To fix, ensure the element is visible before interaction with the locator.waitFor({ state: “visible” }) or expect(locator).toBeVisible().
You can also reduce locator timeout issues by using unique attributes like data-test-id or specific CSS selectors so Playwright can find elements faster, for example: await page.locator(‘[data-test-id=”submit-button”]’).click();
To troubleshoot in this situation, you can add an explicit wait, such as a locator.waitFor() before the assertion. You can also increase the assertion timeout using {timeout: <time>} when the content is consistently slow.
You can also use a page.waitForResponse() for important API calls or even mock slow responses with page.route() so tests don’t depend on actual server speed.
Handling timeouts properly can make a big difference in how stable your Playwright tests are. One of my test cases for this blog kept failing just because an image loaded a bit late. After adjusting the timeout in steps, first for loading, then for visibility, it finally passed. That small fix saved me a lot of time and headaches.
When you’re working with different speeds, animations, or network conditions, things don’t always behave the same way. That’s where platforms like TestMu AI come in handy. It lets you run your Playwright tests across real browsers and networks, so you can spot these issues early and fix them with confidence.
If you are working with Playwright proxy, it’s important to configure timeout settings carefully. Proxies can introduce additional latency, and adjusting timeouts ensures your tests remain stable and don’t fail due to delayed responses.
Did you find this page helpful?
More Related Hubs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance