What are the different methods to handle timeouts in Playwright?

Playwright offers multiple timeout handling methods to control how long operations wait before failing. Understanding these approaches is crucial for building reliable web automation and scraping applications.

Default Timeout Configuration

Global Default Timeout

Set a default timeout for all operations in your test or script:

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const context = await browser.newContext();
  const page = await context.newPage();

  // Set global default timeout (30 seconds)
  page.setDefaultTimeout(30000);

  await page.goto('https://example.com');
  await page.click('button'); // Uses 30s timeout
  await browser.close();
})();

Context-Level Default Timeout

Apply timeout settings to all pages within a browser context:

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const context = await browser.newContext();

  // Set timeout for all pages in this context
  context.setDefaultTimeout(15000);

  const page = await context.newPage();
  await page.goto('https://example.com'); // Uses 15s timeout
  await browser.close();
})();

Per-Action Timeout Configuration

Navigation Timeouts

Control how long to wait for page navigation:

// Set timeout for specific navigation
await page.goto('https://slow-website.com', { timeout: 60000 });

// Wait for navigation with custom timeout
await Promise.all([
  page.waitForNavigation({ timeout: 10000 }),
  page.click('a[href="/next-page"]')
]);

Element Interaction Timeouts

Set timeouts for individual element operations:

// Click with custom timeout
await page.click('button#submit', { timeout: 5000 });

// Fill input with timeout
await page.fill('input[name="email"]', 'user@example.com', { timeout: 3000 });

// Wait for element with timeout
await page.waitForSelector('.loading-spinner', { timeout: 10000 });

Wait Methods and Timeouts

waitForSelector with Timeout

Wait for elements to appear or disappear:

// Wait for element to appear
await page.waitForSelector('.content', { timeout: 15000 });

// Wait for element to be hidden
await page.waitForSelector('.loading', { 
  state: 'hidden', 
  timeout: 20000 
});

// Wait for element to be visible and enabled
await page.waitForSelector('button#submit', { 
  state: 'visible',
  timeout: 5000 
});

waitForLoadState with Timeout

Wait for specific page load states:

// Wait for page to be fully loaded
await page.waitForLoadState('networkidle', { timeout: 30000 });

// Wait for DOM to be ready
await page.waitForLoadState('domcontentloaded', { timeout: 10000 });

Fixed Delays (Use Sparingly)

Sometimes you need to wait for a specific duration:

// Wait for 2 seconds (avoid in production code)
await page.waitForTimeout(2000);

// Better: Wait for specific condition instead
await page.waitForFunction(() => {
  return document.querySelector('.animation').classList.contains('completed');
}, { timeout: 10000 });

Advanced Timeout Patterns

Conditional Waiting with Timeout

Handle dynamic content that may or may not appear:

try {
  // Try to wait for modal, but don't fail if it doesn't appear
  await page.waitForSelector('.modal', { timeout: 3000, state: 'visible' });
  await page.click('.modal button.close');
} catch (error) {
  console.log('Modal did not appear, continuing...');
}

Race Conditions with Multiple Timeouts

Wait for the first of multiple conditions:

const result = await Promise.race([
  page.waitForSelector('.success-message', { timeout: 10000 }),
  page.waitForSelector('.error-message', { timeout: 10000 })
]);

if (await result.textContent() === 'Success!') {
  console.log('Operation succeeded');
} else {
  console.log('Operation failed');
}

Custom Wait Functions

Create reusable timeout patterns:

async function waitForElementWithRetry(page, selector, maxAttempts = 3) {
  for (let i = 0; i < maxAttempts; i++) {
    try {
      await page.waitForSelector(selector, { timeout: 5000 });
      return true;
    } catch (error) {
      if (i === maxAttempts - 1) throw error;
      await page.waitForTimeout(1000); // Wait 1s before retry
    }
  }
}

// Usage
await waitForElementWithRetry(page, '.dynamic-content');

Error Handling and Timeout Exceptions

Handling Timeout Errors

Gracefully handle timeout failures:

try {
  await page.waitForSelector('.slow-loading-element', { timeout: 5000 });
} catch (error) {
  if (error.name === 'TimeoutError') {
    console.log('Element did not load within 5 seconds');
    // Implement fallback behavior
  } else {
    throw error; // Re-throw non-timeout errors
  }
}

Timeout Best Practices

Configure timeouts based on your specific needs:

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const context = await browser.newContext();
  const page = await context.newPage();

  // Conservative global timeout
  page.setDefaultTimeout(30000);

  // Fast operations can use shorter timeouts
  await page.fill('input', 'text', { timeout: 2000 });

  // Slow operations may need longer timeouts
  await page.goto('https://heavy-site.com', { timeout: 60000 });

  // API calls or file uploads
  await page.waitForResponse('**/api/upload', { timeout: 120000 });

  await browser.close();
})();

Timeout Configuration Summary

| Method | Scope | Default | Use Case | |--------|-------|---------|----------| | page.setDefaultTimeout() | Page-level | 30000ms | All page operations | | context.setDefaultTimeout() | Context-level | 30000ms | All pages in context | | { timeout: N } option | Single action | Varies | Specific operations | | waitForTimeout() | Fixed delay | N/A | Explicit waits |

All timeout values are in milliseconds (1000ms = 1 second). Choose appropriate timeouts based on your application's performance characteristics and network conditions.

Related Questions

Get Started Now

WebScraping.AI provides rotating proxies, Chromium rendering and built-in HTML parser for web scraping
Icon