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
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 )
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: [] }
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!
})
Handle errors in evaluate
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 )
}
Use parameters for dynamic values
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!');
});
` )