A Guide for Script Injection in Puppeteer
2/1/2025
Hey there! Laura and Heidi here from SCRNIFY. Today, we're diving deep into script injection with Puppeteer. After spending countless hours working with browsers (and building a screenshot service along the way), we've learned a thing or two about injecting scripts effectively. Let's share what we've discovered!
The Basics: Your Script Injection Toolkit
Puppeteer gives us three main ways to inject scripts:
- By URL (loading from external sources)
- By file path (loading from your local system)
- Raw content (directly injecting JavaScript)
Let's explore each method with real, working examples.
Method 1: External Scripts via URL
const puppeteer = require('puppeteer');
async function injectExternalScript() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
await page.goto('https://example.com');
// Inject jQuery from CDN
await page.addScriptTag({
url: 'https://code.jquery.com/jquery-3.7.1.min.js'
});
// Verify jQuery is working
const jQueryVersion = await page.evaluate(() => {
return jQuery.fn.jquery;
});
console.log(`jQuery version ${jQueryVersion} injected successfully!`);
} finally {
await browser.close();
}
}
injectExternalScript().catch(console.error);
Console output:
jQuery version 3.7.1 injected successfully!
Method 2: Local File Injection
const puppeteer = require('puppeteer');
const path = require('path');
async function injectLocalScript() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
await page.goto('https://example.com');
// Inject local script
await page.addScriptTag({
path: path.join(__dirname, 'custom-script.js')
});
// Verify our custom function exists
const result = await page.evaluate(() => {
return window.myCustomFunction();
});
console.log('Custom script result:', result);
} finally {
await browser.close();
}
}
// custom-script.js content:
/*
window.myCustomFunction = function() {
return 'Hello from custom script!';
};
*/
injectLocalScript().catch(console.error);
Console output:
Custom script result: Hello from custom script!
Method 3: Raw Script Injection
const puppeteer = require('puppeteer');
async function injectRawScript() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
await page.goto('https://example.com');
// Inject raw JavaScript
await page.addScriptTag({
content: `
window.modifyPage = function() {
document.body.style.backgroundColor = '#f0f0f0';
document.querySelector('h1').textContent = 'Modified!';
return 'Page modified successfully!';
};
`
});
// Execute our injected function
const result = await page.evaluate(() => {
return window.modifyPage();
});
console.log('Script execution result:', result);
} finally {
await browser.close();
}
}
injectRawScript().catch(console.error);
Console output:
Script execution result: Page modified successfully!
Advanced Scenarios: Async Scripts and Security
Handling Async Scripts
const puppeteer = require('puppeteer');
async function handleAsyncScript() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
await page.goto('https://example.com');
// Inject async script
await page.addScriptTag({
content: `
window.asyncOperation = async function() {
return new Promise(resolve => {
setTimeout(() => {
resolve('Async operation completed!');
}, 1000);
});
};
`
});
// Wait for async operation
const result = await page.evaluate(async () => {
return await window.asyncOperation();
});
console.log('Async result:', result);
} finally {
await browser.close();
}
}
handleAsyncScript().catch(console.error);
Security Considerations
When injecting scripts, keep these high-level security practices in mind:
const puppeteer = require('puppeteer');
async function secureScriptInjection() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
// Use content security policy
await page.setExtraHTTPHeaders({
'Content-Security-Policy': "script-src 'self' 'unsafe-inline' https://trusted-cdn.com"
});
await page.goto('https://example.com');
// Only inject from trusted sources
await page.addScriptTag({
url: 'https://trusted-cdn.com/script.js'
});
} finally {
await browser.close();
}
}
Comparing Methods: evaluate() vs addScriptTag()
Let's look at the key differences:
const puppeteer = require('puppeteer');
async function compareMethods() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
await page.goto('https://example.com');
// Using evaluate()
const evaluateResult = await page.evaluate(() => {
document.body.style.backgroundColor = 'red';
return 'Modified with evaluate()';
});
console.log('Evaluate result:', evaluateResult);
// Using addScriptTag()
await page.addScriptTag({
content: `
document.body.style.backgroundColor = 'blue';
console.log('Modified with addScriptTag()');
`
});
} finally {
await browser.close();
}
}
compareMethods().catch(console.error);
Method | Execution | Best Used For | Behavior |
---|---|---|---|
evaluate() |
Once | One-off operations | Executes and returns result |
addScriptTag() |
Persistent | Reusable functions | Remains in page context |
Performance Tips
Keep these general performance considerations in mind:
const puppeteer = require('puppeteer');
async function performanceOptimizedInjection() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
// Combine multiple scripts into one
await page.addScriptTag({
content: `
// All your functions in one injection
window.function1 = () => {};
window.function2 = () => {};
window.function3 = () => {};
`
});
// Use async/defer for external scripts
await page.addScriptTag({
url: 'https://example.com/script.js',
type: 'text/javascript',
async: true
});
} finally {
await browser.close();
}
}
Wrapping Up
Script injection in Puppeteer is powerful but requires careful consideration of your use case. Whether you're loading external libraries, injecting custom code, or handling async operations, always remember:
- Choose the right injection method for your needs
- Consider security implications
- Keep performance in mind
- Use error handling appropriate for your use case
We hope this guide helps you master script injection in Puppeteer! If you're looking for a ready-to-use solution for web captures, check out SCRNIFY - we've already handled all these complexities for you! 😉
Cheers, Laura & Heidi 🇦🇹
P.S. Got questions about Puppeteer or web automation? We'd love to hear from you!