Skip to main content
Execute JavaScript in the browser context and inject user scripts that run on every page load.

Methods

page.evaluate()

Executes JavaScript in the page context and returns the result.
page.evaluate(func: Function | string, params?: Array<unknown>): Promise<any>
Parameters:
  • func: Function or string of JavaScript code to execute
  • params (optional): Array of parameters to pass to the function
Returns: Promise<any> - Result of the JavaScript execution Examples:
// Execute a function
const title = await page.evaluate(() => document.title)
console.log('Page title:', title)

// With parameters
const result = await page.evaluate((a, b) => a + b, [5, 10])
console.log('Result:', result)  // 15

// Execute a string
const html = await page.evaluate('document.body.innerHTML')

// Return complex objects
const data = await page.evaluate(() => {
  return {
    title: document.title,
    url: window.location.href,
    links: Array.from(document.querySelectorAll('a')).map(a => a.href)
  }
})
evaluate() runs in the page context, so it has access to the DOM, window, document, and any JavaScript libraries loaded on the page.

page.addUserScript()

Adds a user script that runs on every page load.
page.addUserScript(script: string): Promise<void>
Parameters:
  • script: JavaScript code to execute on every page load
Returns: Promise<void> Example:
await page.addUserScript(`
  console.log('User script loaded on:', window.location.href);

  // Add custom API
  window.customAPI = {
    version: '1.0',
    getData: () => ({ foo: 'bar' })
  };

  // Modify page behavior
  document.addEventListener('DOMContentLoaded', () => {
    console.log('DOM loaded, custom script initialized');
  });
`)

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

// Access custom API
const data = await page.evaluate(() => window.customAPI.getData())
console.log(data)  // { foo: 'bar' }

Complete examples

Extract data from page

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

const products = await page.evaluate(() => {
  return Array.from(document.querySelectorAll('.product')).map(el => {
    const name = el.querySelector('.product-name')?.textContent || ''
    const price = el.querySelector('.product-price')?.textContent || ''
    const image = el.querySelector('img')?.src || ''

    return {
      name: name.trim(),
      price: price.trim(),
      image
    }
  })
})

console.log(`Found ${products.length} products:`)
console.log(products)

Check page state

const pageInfo = await page.evaluate(() => {
  return {
    title: document.title,
    url: window.location.href,
    readyState: document.readyState,
    scrollHeight: document.body.scrollHeight,
    hasJQuery: typeof window.jQuery !== 'undefined',
    hasReact: typeof window.React !== 'undefined'
  }
})

console.log('Page info:', pageInfo)

Manipulate DOM

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

// Modify the page
await page.evaluate(() => {
  // Change background color
  document.body.style.backgroundColor = '#f0f0f0'

  // Hide ads
  document.querySelectorAll('.ad, .advertisement').forEach(ad => {
    ad.style.display = 'none'
  })

  // Add custom content
  const banner = document.createElement('div')
  banner.textContent = 'Custom Banner'
  banner.style.cssText = 'position: fixed; top: 0; width: 100%; background: blue; color: white; padding: 10px; text-align: center; z-index: 9999;'
  document.body.insertBefore(banner, document.body.firstChild)
})

// Take a screenshot of modified page
const screenshot = await page.screenshot()

Call page functions

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

// Call a function defined on the page
const result = await page.evaluate(() => {
  // Assuming the page has a global function `fetchData()`
  if (typeof window.fetchData === 'function') {
    return window.fetchData()
  }
  return null
})

console.log('Page data:', result)

Scroll and interact

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

// Scroll to bottom
await page.evaluate(() => {
  window.scrollTo(0, document.body.scrollHeight)
})

// Wait for lazy-loaded content
await new Promise(resolve => setTimeout(resolve, 2000))

// Check scroll position
const scrollPos = await page.evaluate(() => window.scrollY)
console.log('Scrolled to:', scrollPos)

// Scroll to specific element
await page.evaluate(() => {
  document.querySelector('#target-section')?.scrollIntoView()
})

Inject libraries

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

// Inject jQuery if not present
const hasJQuery = await page.evaluate(() => typeof window.jQuery !== 'undefined')

if (!hasJQuery) {
  await page.addUserScript(`
    const script = document.createElement('script');
    script.src = 'https://code.jquery.com/jquery-3.6.0.min.js';
    document.head.appendChild(script);
  `)

  // Wait for jQuery to load
  await page.waitForFunction(() => typeof window.jQuery !== 'undefined')
  console.log('jQuery injected')
}

// Now use jQuery
const count = await page.evaluate(() => {
  return window.$('p').length
})
console.log(`Found ${count} paragraphs using jQuery`)

Monitor page activity

await page.addUserScript(`
  window.__pageActivity = {
    clicks: 0,
    xhr: 0,
    errors: []
  };

  document.addEventListener('click', () => {
    window.__pageActivity.clicks++;
  });

  const originalFetch = window.fetch;
  window.fetch = function(...args) {
    window.__pageActivity.xhr++;
    return originalFetch.apply(this, args);
  };

  window.addEventListener('error', (e) => {
    window.__pageActivity.errors.push(e.message);
  });
`)

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

// Do some automation
await page.click('#button1')
await page.click('#button2')

// Check activity
const activity = await page.evaluate(() => window.__pageActivity)
console.log('Page activity:', activity)
// { clicks: 2, xhr: 3, errors: [] }

Custom form validation

await page.addUserScript(`
  window.customValidation = {
    validateEmail: (email) => {
      return /^[^@]+@[^@]+\\.[^@]+$/.test(email);
    },
    validatePhone: (phone) => {
      return /^\\d{10}$/.test(phone.replace(/\\D/g, ''));
    }
  };
`)

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

// Use custom validation
const emailValid = await page.evaluate(() => {
  const email = document.querySelector('#email').value
  return window.customValidation.validateEmail(email)
})

if (!emailValid) {
  console.error('Invalid email')
}

Best practices

evaluate() can only return serializable values (no functions, DOM nodes, etc.):
// Good
const text = await page.evaluate(() => {
  return document.querySelector('h1').textContent
})

// Bad - can't return DOM nodes
const element = await page.evaluate(() => {
  return document.querySelector('h1')  // Error!
})
Errors in evaluate() will be thrown in your code:
try {
  const result = await page.evaluate(() => {
    return document.querySelector('.missing').textContent
  })
} catch (error) {
  console.error('Error in page context:', error)
}
Pass values as parameters rather than using string concatenation:
// Good
const result = await page.evaluate((selector) => {
  return document.querySelector(selector)?.textContent
}, ['#title'])

// Avoid
const selector = '#title'
const result = await page.evaluate(`
  document.querySelector('${selector}')?.textContent
`)
User scripts run before page scripts, so you can set up monitoring or modify behavior:
await page.addUserScript(`
  // Runs before page JavaScript
  window.addEventListener('load', () => {
    console.log('Page loaded!');
  });
`)