The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Use page.keyboard.down(key) to hold a key and page.keyboard.up(key) to release it. Run the page action that needs the key held between those calls. For example, hold the left arrow while an action runs:
await page.keyboard.down('ArrowLeft');
try {
// Perform the action that should happen while ArrowLeft is held.
} finally {
await page.keyboard.up('ArrowLeft');
}
The finally block releases the key even if the intervening action throws. Puppeteer’s current API reference displayed version 25.12.0 on October 3, 2026; check the documentation for the version installed in your project if exact version compatibility matters.
As an Amazon Associate I earn from qualifying purchases.
Use down() and up() for a sustained hold
Puppeteer’s virtual keyboard keeps a key pressed in its keyboard state after down() until you call up(). Both methods take a documented key name. Use the same key name to release the key you held.
await page.keyboard.down('ArrowLeft');
try {
await page.locator('#game').click();
// The page action runs while ArrowLeft remains held.
} finally {
await page.keyboard.up('ArrowLeft');
}
The action in the example is illustrative: replace the selector and action with the interaction your page requires. Puppeteer documents down() as dispatching a keydown event and up() as dispatching a keyup event.
#1 Best Overall
Here is a complete Node.js example that launches Chromium, opens a page, focuses an input, holds Shift while pressing the A key, and closes the browser:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto('https://example.com');
// Replace this selector with a focusable input on the page.
await page.locator('input').focus();
await page.keyboard.down('Shift');
try {
await page.keyboard.press('KeyA');
} finally {
await page.keyboard.up('Shift');
}
} finally {
await browser.close();
}
})();
The example assumes the target page has an input; change the selector to match the page being automated. If the input does not exist, the focus step will fail before the key is held.
Rank #2
Choose between down(), press(), and type()
| Need | Use | Behavior |
|---|---|---|
| Keep a key held while other code runs | down(key), then up(key) |
Leaves the key down between calls; you control when it is released. |
| Send one key press, optionally with a timed interval | press(key, { delay }) |
A shortcut for down and up. The optional delay is milliseconds between keydown and keyup; it defaults to zero. |
| Enter ordinary text | type(text) |
Sends text character by character, with key events for each character. Its optional delay is between key events and defaults to zero. |
| Press a key on a particular element | ElementHandle.press(key) |
Focuses that element, then performs the down/up press. |
press() is not the sustained-hold method: it automatically releases the key. Use explicit down() and up() when intervening actions must happen while the key remains held.
Hold modifiers across key presses
Modifiers remain active for subsequent key presses until released. Puppeteer documents Shift, Meta, Control, and Alt as modifiers. This example holds Shift while pressing the left arrow, then releases Shift:
await page.keyboard.down('Shift');
try {
await page.keyboard.press('ArrowLeft');
} finally {
await page.keyboard.up('Shift');
}
Holding Shift does not make type() convert its string to uppercase; use key presses when the intended behavior depends on a modifier.
Use valid key names and focus the right target
Puppeteer accepts values in its documented KeyInput set. Examples include ArrowLeft, ArrowDown, Backspace, Enter, Shift, Control, Alt, and Meta, along with letter and digit representations. Consult the Puppeteer Keyboard API reference for the complete accepted set rather than guessing a spelling.
Rank #4
Keyboard input is sent to the focused page element. Focus the intended element with your normal page interaction before sending keys. If you use ElementHandle.press(), that method focuses its element before issuing the press.
Free tools Windows power users keep installed
One-click scans. No signup required.
Troubleshoot key-hold problems
- The key seems to release immediately: Check that you used
down()rather thanpress().press()includes both keydown and keyup. - The page does not react: Confirm the page and intended element have focus, and check that the key name is a valid
KeyInput. - A modifier affects later actions unexpectedly: Ensure every deliberate
down()has a matchingup(). Usetry/finallyaround work that can fail. - Text entry does not behave like a special key: Use
press()or down/up for arrows and other special keys; usetype()for ordinary text. - A repeated down behaves differently: Calling
down()again for a key that is already pressed sets the event’s repeat flag to true. Do not use repeated calls as a substitute for a single hold unless repeated keydown behavior is wanted. - A macOS shortcut such as Command+A does not work: The current Keyboard class reference notes a limitation for keyboard shortcuts such as ⌘ A for Select All on macOS. This caveat is specific to shortcuts on macOS; it does not mean all key actions fail there.
Or skip the browser setup
For screenshot capture rather than custom keyboard interaction, ScreenshotNeo offers a one-request screenshot API. It does not replace Puppeteer’s key-hold control; it is an alternative when the goal is to capture a page.
Best Value
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options. Cookie banners are accepted and removed before capture, along with known newsletter popups and chat widgets; those cleanup steps can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers report the page verdict and billing status. ScreenshotNeo also has an MCP server for AI agents, including Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.
Frequently Asked Questions
Does Puppeteer wait a fixed amount of time when a key is held with down() and up()?
No fixed hold duration is required by that pattern. The key remains down while your code runs between the two calls; use press() with its optional delay when you want a timed down/up press.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsQuick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




