Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
WorkerConf 2021 - Browser automation with Puppe...
Search
Jecelyn Yeen
June 25, 2021
Programming
1.9k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
WorkerConf 2021 - Browser automation with Puppeteer
Jecelyn Yeen
June 25, 2021
More Decks by Jecelyn Yeen
See All by Jecelyn Yeen
My Journey as Technical Presenter
jecfish
0
1k
Becoming a GDE
jecfish
0
4k
How to get started in IT Freelancing
jecfish
1
300
New Web API & Stylings
jecfish
3
770
如何打造高性能且SEO友好的单页应用(SPA)
jecfish
2
930
JS SEO
jecfish
4
1.6k
Web Performance Optimization
jecfish
5
1.8k
Have Fun with Angular
jecfish
0
130
RxJs Trex
jecfish
0
720
Other Decks in Programming
See All in Programming
MySQLとPostgreSQLって何が違うの?
akagami
PRO
0
160
이 함수, 실패하면 어떻게 되나요? null부터 Rich Errors까지, Kotlin 에러 처리 15년
haeti2
0
120
go-spidermonkeyでAIエージェントのCode Modeを実装する
syumai
3
1.5k
AI時代に学ぶ 好きなルール 嫌いなルール Linter編
shorty5121
0
800
Kiroで創り、AgentCoreで繋ぐ!AWSで実践する「AI-DLC」から「AIエージェント統合」までの最新地図
licux
2
260
[PyCon KR 2026] More Variants, More Diversity for AI Accelerators
achimnol
0
130
AIに既存システムを理解させる技術 ~レガシーを見捨てないハーネスエンジニアリング入門~
ochtum
0
200
型解析で実現する Go の言語内 DSL / Conference に Go! タイムテーブルの歩き方 for Gophers
mazrean
0
120
私のClaude Code活用法 (個人開発編) - PHPerKaigi mini #4(2026/08/24)
panda_program
1
210
Hono + Inertia + React で LP を構築した話
oukayuka
2
200
Vibes Containers 〜AIで変わるコンテナ設計と運用〜
tkikuc
1
450
「AI時代、配布するPythonコードをどう守るか: 難読化の実験と判断軸」 #PyconJP2026
pkshadeck
PRO
2
140
Featured
See All Featured
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Are puppies a ranking factor?
jonoalderson
2
3.9k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
700
4 Signs Your Business is Dying
shpigford
187
23k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.4k
Git: the NoSQL Database
bkeepers
PRO
432
67k
Optimizing for Happiness
mojombo
378
71k
AI: The stuff that nobody shows you
jnunemaker
PRO
9
970
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
810
The Invisible Side of Design
smashingmag
301
52k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
450
Transcript
@JecelynYeen Developer advocate, Google @ChromeDevTools
None
My road bike
Mountain bike My road bike
Mountain bike Hiking, hot and humid My road bike
Mountain bike Hiking, hot and humid Hiking, Switzerland My road
bike
None
Browser automation with Puppeteer
PM YANG Professional developer PAUL
PM YANG I want a daily email on our server’s
internet speed. Professional developer PAUL
PM YANG I want a daily email on our server’s
internet speed. Professional developer PAUL Why does he need that?
PM YANG It’s easy. Go to fast.com on the server
and send me the screenshot.
PM YANG It’s easy. Go to fast.com on the server
and send me the screenshot. Professional developer PAUL I never said it’s hard...
None
None
Professional developer PAUL There are 2 ways to do this:
Manually 1. Login to server 2. Open a browser 3. Go to fast.com 4. Take a screenshot 5. Send email
Professional developer PAUL There are 2 ways to do this:
Manually 1. Login to server 2. Open a browser 3. Go to fast.com 4. Take a screenshot 5. Send email Automate it 1. Schedule a daily server task 2. Automate screenshot 3. Automate email sending
Professional developer PAUL Researching...
Professional developer PAUL Researching... Puppeteer
None
Browser automation library for Node.js
Control a browser with modern JavaScript API.
const puppeteer = require('puppeteer'); (async () => { })();
const puppeteer = require('puppeteer'); (async () => { const browser
= await puppeteer.launch(); })();
const puppeteer = require('puppeteer'); (async () => { const browser
= await puppeteer.launch(); const page = await browser.newPage(); })();
const puppeteer = require('puppeteer'); (async () => { const browser
= await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://fast.com/'); })();
const puppeteer = require('puppeteer'); (async () => { const browser
= await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://fast.com/'); await page.screenshot({ path: 'img/screenshot-yyyyMMdd.png' }); })();
const puppeteer = require('puppeteer'); (async () => { const browser
= await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://fast.com/'); await page.screenshot({ path: 'img/screenshot-yyyyMMdd.png' }); await browser.close(); })();
Not working
None
const puppeteer = require('puppeteer'); (async () => { const browser
= await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://fast.com/'); await page.waitForSelector('.speed-results-container.succeeded'); await page.screenshot({ path: 'img/screenshot-yyyyMMdd.png' }); await browser.close(); })();
Run it again
Professional developer PAUL
PM YANG Cool, it will be great if to have
date in the screenshot. Possible?
const puppeteer = require('puppeteer'); (async () => { const browser
= await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://fast.com/'); await page.waitForSelector('.speed-results-container.succeeded'); await page.$eval('#your-speed-message', (el, dt) => { el.innerText = `Internet speed as of ${dt} is`; }, 'yyyy-MM-dd')); await page.screenshot({ path: `img/screenshot-yyyyMMdd.png` }); await browser.close(); })();
PM YANG I want...
// Save as pdf, only work in headless mode await
page.pdf({ path: `doc/speed-yyyyMMdd.pdf` }); // Click to show more details await page.click('#show-more-details-link'); await page.waitForSelector('#upload-label.succeeded', { timeout: 0 }); // Emulate mobile view and save screenshot // src/common/DeviceDescriptors.ts const tablet = puppeteer.devices['iPad Mini']; await page.emulate(tablet); await page.screenshot({ path: `img/screenshot-yyyyMMdd.png` }); // Reload page await page.reload();
// Save as pdf, only work in headless mode await
page.pdf({ path: `doc/speed-yyyyMMdd.pdf` }); // Click to show more details await page.click('#show-more-details-link'); await page.waitForSelector('#upload-label.succeeded', { timeout: 0 }); // Emulate mobile view and save screenshot // src/common/DeviceDescriptors.ts const tablet = puppeteer.devices['iPad Mini']; await page.emulate(tablet); await page.screenshot({ path: `img/screenshot-yyyyMMdd.png` }); // Reload page await page.reload();
// Save as pdf, only work in headless mode await
page.pdf({ path: `doc/speed-yyyyMMdd.pdf` }); // Click to show more details await page.click('#show-more-details-link'); await page.waitForSelector('#upload-label.succeeded', { timeout: 0 }); // Emulate mobile view and save screenshot // src/common/DeviceDescriptors.ts const tablet = puppeteer.devices['iPad Mini']; await page.emulate(tablet); await page.screenshot({ path: `img/screenshot-yyyyMMdd.png` }); // Reload page await page.reload();
// Save as pdf, only work in headless mode await
page.pdf({ path: `doc/speed-yyyyMMdd.pdf` }); // Click to show more details await page.click('#show-more-details-link'); await page.waitForSelector('#upload-label.succeeded', { timeout: 0 }); // Emulate mobile view and save screenshot // src/common/DeviceDescriptors.ts const tablet = puppeteer.devices['iPad Mini']; await page.emulate(tablet); await page.screenshot({ path: `img/screenshot-yyyyMMdd.png` }); // Reload page await page.reload();
github.com/puppeteer
❤
const browser = await puppeteer.launch(); const page = await browser.newPage();
await page.goto('https://v8.dev/blog/10-years'); // Create screenshots of your web app in Light Mode and Dark Mode. // Tip: check out `npx dark-mode-screenshot` for more options! await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'light' }]); await page.screenshot({ path: 'light.png', fullPage: true }); await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]); await page.screenshot({ path: 'dark.png', fullPage: true }); await browser.close();
const browser = await puppeteer.launch(); const page = await browser.newPage();
await page.goto('https://mathiasbynens.be/demo/timezone'); page.evaluate(() => { globalThis.date = new Date(1479579154987); }); await page.emulateTimezone('America/Buenos_Aires'); console.log(await page.evaluate(() => date.toString())); // → 'Sat Nov 19 2016 15:12:34 GMT-0300 (Argentina Standard Time)' await page.emulateTimezone('Asia/Kuala_Lumpur'); console.log(await page.evaluate(() => date.toString())); // → 'Sun Nov 20 2016 02:12:34 GMT+0800 (Malaysia Time)' await browser.close();
const browser = await puppeteer.launch(); const page = await browser.newPage();
await page.goto('https://developer.chrome.com/tags/devtools/'); await page.emulateVisionDeficiency('blurredVision'); await page.screenshot({ path: 'blurred-vision.png', fullPage: true }); await page.emulateVisionDeficiency('achromatopsia'); await page.screenshot({ path: 'achromatopsia.png', fullPage: true }); await page.emulateVisionDeficiency('deuteranopia'); await page.screenshot({ path: 'deuteranopia.png', fullPage: true }); await browser.close();
addyosmani.com/blog/ puppeteer-recipes/
const browser = await puppeteer.launch();
const browser = await puppeteer.launch(); // Launch options const browser
= await puppeteer.launch({ product: 'firefox' });
const browser = await puppeteer.launch(); // Launch options const browser
= await puppeteer.launch({ product: 'firefox' }); const browser = await puppeteer.launch({ headless: false, slowMo: 3000 });
const browser = await puppeteer.launch(); // Launch options const browser
= await puppeteer.launch({ product: 'firefox' }); const browser = await puppeteer.launch({ headless: false, slowMo: 3000 }); const browser = await puppeteer.launch({ devtools: true });
goo.gle/devtools-blog
@JecelynYeen Developer advocate, Google @ChromeDevTools