Use Playwright to Inject Shortcut Keys into Any Web Page - for example to download all images image 39

Use Playwright to Inject Shortcut Keys into Any Web Page – for example to download all images

Adding a short cut key combination to a web application or web site can be quite powerful. When the short cut key combination is activated – things can happen. Things that you have defined on top of everything the web application already offers. In this article I describe how I have used Playwright to inject a short cut key combination into a web site. This hotkey – activated by simply pressing ctrl+b – runs a function that downloads all images in the current browser context to the local file system. The function that is executed is a Node (JS) function that can on the one hand access the complete browser context (including DOM, JavaScript context, local storage, cookies etc) and on the other hand has all of Node and NPM at its disposal. A pretty powerful combination.

This article is just an example of how you can rich functionality to your SaaS web applications, favorite blogs, cloud consoles and anything you run in a browser. By running the browser through Playwright, you get the normal browser functionality as well as the world of Node through the wrapper and bridge that Playwright provides. I have introduced Playwright in an earlier article and if you do not know Playwright yet, I strongly suggest you read that article.

In short: Playwright is an open source software library that gives us a deus in machina – a robot in our browser do perform power operations. This opens up opportunities from automated testing to tactical integration and RPA (Robotic Process Automation), and from deeplink bookmarks, screen scraping, web app health monitoring (smoketests) and customized web applications. Playwright is a fairly new (2020), open-source, JavaScript-based, cross-browser automation library for end-to-end testing.

How to add a short cut key to a 3rd party Web Application

You might wonder how it is we can extend an existing web site or web application – especially when it is not our own. What we do is load the web site or web application into the embedded browser that we run from a Node application using the Playwright library. This allows us to wrap the browser with our own application logic. In that logic, we can manipulate the DOM and JavaScript context of the page that is currently loaded.

In this case, a function handleShortCutKey is injected to the page.
// create a shortcut key (ctrl + b) that triggers the JS function to download all images
const shortCutJS = `async function handleShortCutKey(e) { if (‘KeyB’==e.code && e.ctrlKey) { // ctrl + b
const result = await window.imageDownloadFunction() ; // invoke the Node function that was exposed to the browser context
console.log(result+” images were downloaded”)
document.addEventListener(‘keyup’, handleShortCutKey);
await page.addScriptTag({ content: shortCutJS })
[/CODE]This function is set up as an event listener for the key up event. In handleShortCutKey, we test for the short cut key combination ctrl+b. If that key has been activated, the function will invoke a function called imageDownloadFunction.


This second function is not part of the 3rd party web application. Nor does it really exist in the browser context. This function is a placeholder for a function in the Node application that started the browser and loaded the web application. Using the statement

await context.exposeBinding(‘imageDownloadFunction’, allImageDownloader)

the function allImageDownloader in the Node application has been exposed on the browser window object where it can be invoked from within the browser context; the name of this proxy is imageDownloadFunction.

var streamImageFromURL = function (imageURL, imageFilename) {

const allImageDownloader = async (source) => {
console.log(`go download all images in the page`)
// using the page object in, get all img elements and return a collection of image objects to be processed in the Node context
const images = await$$eval(“img”, (images) => => { return {src: image.src, alt: image.alt, width:image.clientWidth, height:image.clientHeight}})
// for each image of substantial size – determine the name of the image file and invoke the function streamImageFromURL to download the image and save it locally
images.forEach(image => { if (image.width * image.height > 2500) {
const startIndex = image.src.lastIndexOf(“/”) + 1 // do not include /
const endIndex = image.src.indexOf(“?”)> -1? image.src.indexOf(“?”):500
const imageFilename = image.src.substring(startIndex,endIndex)
console.log(`download ${image.src} as ${imageFilename}`)
streamImageFromURL(image.src, imageFilename);
return images.length

(async () => {
const browser = await chromium.launch({ headless: false })
const context = await browser.newContext()
// expose a Node function as binding to the page (to be invoked from the function)
await context.exposeBinding(‘imageDownloadFunction’, allImageDownloader)

await page.goto(URL);

The next figure shows the the complete set up. Function handleShortCutKey lives inside the browser, added to the web application. This function is called when the user activates ctrl+b. Through the bridge to the Node/Playwright context, the function invokes the Node function allImageDownloader. This function retrieves a list of all image elements in the web page – using the Playwright page.$$eval function. It then retrieves the contents of all these images and writes it to the local file system.


What is achieved: any web application or website can be loaded in the embedded browser. Automatically, a function and a shortcut key combination are set up inside the web application. When the user presses ctrl+b , all images are downloaded.

Of course, downloaded all images is just an example of what any short cut key triggered function can do. You can add functions for all kinds of actions to all kinds of web sites in the same way. And thus create web sites and web applications that are more functional and more tailored to your needs.


I have introduced Playwright in an earlier article

Source code for this article:

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.