Puppeteer Integration
Puppeteer connects to Meshbrow browsers via the standard CDP WebSocket endpoint.Basic Connection
const puppeteer = require('puppeteer-core');
const browser = await puppeteer.connect({
browserWSEndpoint: 'wss://api.meshbrow.dev/cdp/ses_abc123?token=ct_...',
});
const pages = await browser.pages();
const page = pages[0];
await page.goto('https://example.com');
console.log(await page.title());
With the SDK
const { Meshbrow } = require('@meshbrow/sdk');
const puppeteer = require('puppeteer-core');
const client = new Meshbrow({ apiKey: process.env.MESHBROW_API_KEY });
const session = await client.sessions.create({
proxy: { type: 'residential', country: 'US' },
stealth: 'max',
});
const browser = await puppeteer.connect({
browserWSEndpoint: session.cdpUrl,
});
const page = (await browser.pages())[0];
await page.goto('https://nowsecure.nl');
// Take screenshot
await page.screenshot({ path: 'stealth-test.png', fullPage: true });
// Cleanup
await browser.disconnect();
await client.sessions.destroy(session.id);
Intercepting Requests
const page = (await browser.pages())[0];
await page.setRequestInterception(true);
page.on('request', (request) => {
// Block images and CSS for faster scraping
if (['image', 'stylesheet', 'font'].includes(request.resourceType())) {
request.abort();
} else {
request.continue();
}
});
await page.goto('https://example.com');
Extracting Data
const page = (await browser.pages())[0];
await page.goto('https://example.com/products');
const products = await page.evaluate(() => {
return Array.from(document.querySelectorAll('.product-card')).map((el) => ({
name: el.querySelector('.name')?.textContent?.trim(),
price: el.querySelector('.price')?.textContent?.trim(),
url: el.querySelector('a')?.href,
}));
});
console.log(JSON.stringify(products, null, 2));
Using Cookies from Profiles
const session = await client.sessions.create({
profileId: 'prof_github_bot',
stealth: 'max',
});
const browser = await puppeteer.connect({
browserWSEndpoint: session.cdpUrl,
});
const page = (await browser.pages())[0];
// Navigate directly to authenticated page
await page.goto('https://github.com/dashboard');
// Already logged in from profile cookies!
Session Recording
const page = (await browser.pages())[0];
// Start tracing
await page.tracing.start({ path: 'trace.json', screenshots: true });
await page.goto('https://example.com');
await page.click('.button');
await page.tracing.stop();
Handling Dynamic Content
const page = (await browser.pages())[0];
await page.goto('https://example.com/infinite-scroll');
// Scroll and wait for new content
let previousHeight = 0;
while (true) {
const currentHeight = await page.evaluate(() => document.body.scrollHeight);
if (currentHeight === previousHeight) break;
previousHeight = currentHeight;
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
await page.waitForTimeout(1500); // Wait for lazy loading
}
const allItems = await page.$$eval('.item', (els) =>
els.map((el) => el.textContent?.trim())
);
Tips
Always call
browser.disconnect() (not browser.close()) when done.
Closing would kill the Meshbrow session. Use the SDK’s destroy() method instead.- Use
puppeteer-core(notpuppeteer) since the browser is remote - Set
defaultViewport: nullto use Meshbrow’s configured viewport - Add
--disable-web-securityonly in test mode, never in production