Skip to main content
Wait for elements, JavaScript conditions, and network requests before proceeding with automation.

Methods

page.waitForSelector()

Waits for an element matching the selector to appear in the DOM.
page.waitForSelector(selector: string, options?: WaitForOptions): Promise<void>
Parameters:
  • selector: CSS selector for the element to wait for
  • options (optional): Wait options
Options:
interface WaitForOptions {
  timeout?: number    // Timeout in milliseconds (default: 60000)
  times?: number      // Number of retry attempts (default: 600)
  interval?: number   // Interval between attempts in ms (default: 100)
}
Returns: Promise<void> Examples:
// Wait for element (default 60s timeout)
await page.waitForSelector('.loaded-content')

// Custom timeout (5 seconds)
await page.waitForSelector('#modal', { timeout: 5000 })

// Custom retry behavior
await page.waitForSelector('.dynamic-element', {
  timeout: 30000,
  times: 300,
  interval: 100
})

page.waitForFunction()

Waits until a function returns a truthy value.
page.waitForFunction(
  fn: Function,
  options?: WaitForOptions,
  parameters?: unknown[]
): Promise<void>
Parameters:
  • fn: Function to evaluate repeatedly until it returns truthy
  • options (optional): Wait options
  • parameters (optional): Parameters to pass to the function
Returns: Promise<void> Examples:
// Wait for page ready state
await page.waitForFunction(() => document.readyState === 'complete')

// Wait for custom condition
await page.waitForFunction(() => {
  return document.querySelectorAll('.product').length > 0
})

// With parameters
await page.waitForFunction(
  (minCount) => document.querySelectorAll('.item').length >= minCount,
  {},
  [10]
)

// With timeout
await page.waitForFunction(
  () => window.dataLoaded === true,
  { timeout: 10000 }
)

page.waitForRequest()

Waits for a matching HTTP request to occur.
page.waitForRequest(
  matcher: string | RequestMatchFunction,
  options?: WaitForOptions
): Promise<Request>
Parameters:
  • matcher: URL string or predicate function to match requests
  • options (optional): Wait options
RequestMatchFunction:
type RequestMatchFunction = (request: Request) => boolean

interface Request {
  url: string
  method: string
  headers: Record<string, string>
}
Returns: Promise<Request> - The matched request Examples:
// Wait for specific URL
const request = await page.waitForRequest('https://api.example.com/data')
console.log('API request detected:', request.url)

// Wait with predicate function
const apiRequest = await page.waitForRequest((req) => {
  return req.url.includes('/api/') && req.method === 'POST'
})
console.log('POST request to API:', apiRequest.url)

// With timeout
const request = await page.waitForRequest(
  'https://slow-api.example.com/data',
  { timeout: 120000 }  // 2 minutes
)

Complete examples

Wait for page load

await page.goto('https://example.com')

// Wait for multiple indicators
await Promise.all([
  page.waitForSelector('#main-content'),
  page.waitForFunction(() => document.readyState === 'complete'),
  page.waitForFunction(() => {
    return document.querySelectorAll('.item').length > 0
  })
])

console.log('Page fully loaded and ready')

Wait for dynamic content

await page.goto('https://example.com/products')

// Wait for loading spinner to disappear
await page.waitForFunction(() => {
  const spinner = document.querySelector('.loading-spinner')
  return spinner === null || spinner.style.display === 'none'
})

// Wait for products to load
await page.waitForSelector('.product-grid')
await page.waitForFunction(() => {
  return document.querySelectorAll('.product').length >= 10
})

console.log('Products loaded')

Wait for API response

await page.goto('https://example.com/app')

// Click button that triggers API call
await page.click('#load-data-button')

// Wait for specific API request
const request = await page.waitForRequest((req) => {
  return req.url.includes('/api/users') && req.method === 'GET'
})

console.log('API request made:', request.url)

// Wait for data to appear
await page.waitForSelector('.user-list')

Sequential waits

// Step 1: Navigate to login
await page.goto('https://example.com/login')

// Step 2: User logs in on their device
await page.waitForAuthentication(
  async (page) => {
    return window.location.pathname === '/dashboard'
  },
  { timeout: 120000 }
)

// Step 3: Wait for dashboard content to load
await page.waitForSelector('.dashboard-widget')

console.log('User authenticated, dashboard loaded')

Timeout handling

async function waitForElementSafely(selector, timeout = 10000) {
  try {
    await page.waitForSelector(selector, { timeout })
    return true
  } catch (error) {
    console.error(`Element ${selector} not found within ${timeout}ms`)
    return false
  }
}

const modalAppeared = await waitForElementSafely('#modal', 5000)

if (modalAppeared) {
  await page.click('#modal .close-button')
} else {
  console.log('No modal to close')
}

Wait for multiple conditions

await page.goto('https://example.com/interactive')

// Wait for all conditions to be true
await Promise.all([
  // Element present
  page.waitForSelector('#app-container'),

  // JavaScript loaded
  page.waitForFunction(() => typeof window.app !== 'undefined'),

  // Data fetched
  page.waitForFunction(() => window.app?.dataReady === true),

  // No loading indicators
  page.waitForFunction(() => {
    return document.querySelectorAll('.loading').length === 0
  })
])

console.log('App fully initialized and ready')

Wait for text content

// Wait for specific text to appear
await page.waitForFunction((searchText) => {
  return document.body.innerText.includes(searchText)
}, {}, ['Success'])

console.log('Success message appeared')

// Wait for element with specific text
await page.waitForFunction(() => {
  const el = document.querySelector('.status')
  return el && el.textContent.trim() === 'Complete'
})

Poll for changes

await page.goto('https://example.com/live-data')

// Wait for count to reach threshold
await page.waitForFunction(() => {
  const countEl = document.querySelector('.count')
  if (!countEl) return false

  const count = parseInt(countEl.textContent, 10)
  return count >= 100
}, { timeout: 60000 })

console.log('Count reached 100')

Wait for network idle

await page.goto('https://example.com/app')

// Wait for no API calls for 2 seconds
let lastRequestTime = Date.now()

await page.on('xhr', () => {
  lastRequestTime = Date.now()
})

await page.waitForFunction(() => {
  return Date.now() - lastRequestTime > 2000
}, { timeout: 30000 })

console.log('Network idle for 2 seconds')

Best practices

Wait for elements before clicking or typing:
await page.waitForSelector('#button')
await page.click('#button')
Set timeouts based on expected load times:
// Fast operation
await page.waitForSelector('.quick', { timeout: 5000 })

// Slow API
await page.waitForRequest('/slow-api', { timeout: 120000 })
Always catch timeout errors gracefully:
try {
  await page.waitForSelector('.optional-element', { timeout: 5000 })
} catch (error) {
  console.log('Optional element not found, continuing...')
}
Wait for several conditions to ensure page is ready:
await Promise.all([
  page.waitForSelector('.content'),
  page.waitForFunction(() => document.readyState === 'complete')
])