0
# Input Simulation
1
2
Realistic keyboard, mouse, and touchscreen input simulation with timing controls and platform-specific key mappings.
3
4
## Capabilities
5
6
### Keyboard Interface
7
8
Provides keyboard input simulation with support for key combinations, text typing, and special keys.
9
10
```typescript { .api }
11
interface Keyboard {
12
/** Press key down (without releasing) */
13
down(key: string, options?: KeyDownOptions): Promise<void>;
14
/** Release key */
15
up(key: string): Promise<void>;
16
/** Press and release key */
17
press(key: string, options?: PressOptions): Promise<void>;
18
/** Type text character by character */
19
type(text: string, options?: TypeOptions): Promise<void>;
20
/** Send single character */
21
sendCharacter(char: string): Promise<void>;
22
}
23
24
interface KeyDownOptions {
25
/** Text to insert */
26
text?: string;
27
/** Commands to send (Mac only) */
28
commands?: string[];
29
}
30
31
interface PressOptions {
32
/** Delay between key down and up */
33
delay?: number;
34
/** Text to insert */
35
text?: string;
36
/** Commands to send (Mac only) */
37
commands?: string[];
38
}
39
40
interface TypeOptions {
41
/** Delay between key presses */
42
delay?: number;
43
}
44
```
45
46
**Usage Examples:**
47
48
```typescript
49
import puppeteer from "puppeteer-core";
50
51
const browser = await puppeteer.launch({ executablePath: "/path/to/chrome" });
52
const page = await browser.newPage();
53
await page.goto("https://example.com");
54
55
const keyboard = page.keyboard;
56
57
// Basic typing
58
await page.focus("#text-input");
59
await keyboard.type("Hello World!", { delay: 100 });
60
61
// Key combinations
62
await keyboard.down("Control");
63
await keyboard.press("a"); // Select all
64
await keyboard.up("Control");
65
66
await keyboard.down("Control");
67
await keyboard.press("c"); // Copy
68
await keyboard.up("Control");
69
70
// Special keys
71
await keyboard.press("Tab");
72
await keyboard.press("Enter");
73
await keyboard.press("Escape");
74
await keyboard.press("Backspace");
75
76
// Arrow keys and navigation
77
await keyboard.press("ArrowUp");
78
await keyboard.press("ArrowDown");
79
await keyboard.press("ArrowLeft");
80
await keyboard.press("ArrowRight");
81
82
await keyboard.press("Home");
83
await keyboard.press("End");
84
await keyboard.press("PageUp");
85
await keyboard.press("PageDown");
86
87
// Function keys
88
await keyboard.press("F1");
89
await keyboard.press("F12");
90
91
// Modifier combinations
92
await keyboard.down("Shift");
93
await keyboard.press("ArrowRight"); // Select text
94
await keyboard.up("Shift");
95
96
await keyboard.down("Alt");
97
await keyboard.press("Tab"); // Alt+Tab
98
await keyboard.up("Alt");
99
100
await browser.close();
101
```
102
103
### Mouse Interface
104
105
Provides mouse input simulation including movement, clicking, dragging, and scrolling.
106
107
```typescript { .api }
108
interface Mouse {
109
/** Move mouse to coordinates */
110
move(x: number, y: number, options?: MouseMoveOptions): Promise<void>;
111
/** Click at coordinates */
112
click(x: number, y: number, options?: ClickOptions): Promise<void>;
113
/** Press mouse button down */
114
down(options?: MouseDownOptions): Promise<void>;
115
/** Release mouse button */
116
up(options?: MouseUpOptions): Promise<void>;
117
/** Scroll mouse wheel */
118
wheel(options?: MouseWheelOptions): Promise<void>;
119
/** Drag from current position to target */
120
drag(start: { x: number; y: number }, target: { x: number; y: number }): Promise<void>;
121
/** Drag and drop operation */
122
dragAndDrop(start: { x: number; y: number }, target: { x: number; y: number }, options?: DragAndDropOptions): Promise<void>;
123
}
124
125
interface MouseMoveOptions {
126
/** Number of intermediate steps */
127
steps?: number;
128
}
129
130
interface ClickOptions {
131
/** Mouse button to click */
132
button?: "left" | "right" | "middle";
133
/** Number of clicks */
134
clickCount?: number;
135
/** Delay between mousedown and mouseup */
136
delay?: number;
137
}
138
139
interface MouseDownOptions {
140
/** Mouse button to press */
141
button?: "left" | "right" | "middle";
142
/** Number of clicks */
143
clickCount?: number;
144
}
145
146
interface MouseUpOptions {
147
/** Mouse button to release */
148
button?: "left" | "right" | "middle";
149
/** Number of clicks */
150
clickCount?: number;
151
}
152
153
interface MouseWheelOptions {
154
/** Horizontal scroll delta */
155
deltaX?: number;
156
/** Vertical scroll delta */
157
deltaY?: number;
158
}
159
160
interface DragAndDropOptions {
161
/** Delay during drag operation */
162
delay?: number;
163
}
164
```
165
166
**Usage Examples:**
167
168
```typescript
169
const mouse = page.mouse;
170
171
// Basic mouse operations
172
await mouse.move(100, 200);
173
await mouse.click(100, 200);
174
175
// Different click types
176
await mouse.click(300, 400, { button: "right" }); // Right-click
177
await mouse.click(500, 600, { button: "middle" }); // Middle-click
178
await mouse.click(700, 800, { clickCount: 2 }); // Double-click
179
180
// Mouse down/up for custom timing
181
await mouse.move(150, 250);
182
await mouse.down();
183
await page.waitForTimeout(1000); // Hold for 1 second
184
await mouse.up();
185
186
// Drag operations
187
await mouse.move(100, 100);
188
await mouse.down();
189
await mouse.move(200, 200, { steps: 10 }); // Smooth movement
190
await mouse.up();
191
192
// Drag and drop
193
await mouse.dragAndDrop(
194
{ x: 100, y: 100 },
195
{ x: 300, y: 300 },
196
{ delay: 100 }
197
);
198
199
// Scrolling
200
await mouse.move(500, 500);
201
await mouse.wheel({ deltaY: -100 }); // Scroll up
202
await mouse.wheel({ deltaY: 100 }); // Scroll down
203
await mouse.wheel({ deltaX: -50 }); // Scroll left
204
await mouse.wheel({ deltaX: 50 }); // Scroll right
205
206
// Complex mouse interactions
207
const element = await page.$("#draggable");
208
if (element) {
209
const box = await element.boundingBox();
210
if (box) {
211
// Click and drag element
212
await mouse.move(box.x + box.width / 2, box.y + box.height / 2);
213
await mouse.down();
214
await mouse.move(box.x + 100, box.y + 100, { steps: 5 });
215
await mouse.up();
216
}
217
}
218
```
219
220
### Touchscreen Interface
221
222
Provides touch input simulation for mobile and touch-enabled devices.
223
224
```typescript { .api }
225
interface Touchscreen {
226
/** Tap at coordinates */
227
tap(x: number, y: number): Promise<void>;
228
/** Start touch at coordinates */
229
touchStart(touches: TouchPoint[]): Promise<void>;
230
/** Move touch points */
231
touchMove(touches: TouchPoint[]): Promise<void>;
232
/** End touch */
233
touchEnd(): Promise<void>;
234
}
235
236
interface TouchPoint {
237
x: number;
238
y: number;
239
/** Touch identifier for multi-touch */
240
id?: number;
241
/** Touch radius */
242
radiusX?: number;
243
radiusY?: number;
244
/** Touch rotation angle */
245
rotationAngle?: number;
246
/** Touch pressure */
247
force?: number;
248
}
249
```
250
251
**Usage Examples:**
252
253
```typescript
254
const touchscreen = page.touchscreen;
255
256
// Basic tap
257
await touchscreen.tap(200, 300);
258
259
// Multi-touch gestures
260
await touchscreen.touchStart([
261
{ x: 100, y: 100, id: 0 },
262
{ x: 200, y: 200, id: 1 }
263
]);
264
265
// Pinch gesture (zoom out)
266
await touchscreen.touchMove([
267
{ x: 110, y: 110, id: 0 },
268
{ x: 190, y: 190, id: 1 }
269
]);
270
271
await touchscreen.touchEnd();
272
273
// Swipe gesture
274
await touchscreen.touchStart([{ x: 300, y: 400 }]);
275
await touchscreen.touchMove([{ x: 100, y: 400 }]); // Swipe left
276
await touchscreen.touchEnd();
277
278
// Complex touch interaction
279
const button = await page.$("#touch-button");
280
if (button) {
281
const box = await button.boundingBox();
282
if (box) {
283
await touchscreen.tap(
284
box.x + box.width / 2,
285
box.y + box.height / 2
286
);
287
}
288
}
289
```
290
291
### Key Constants and Mappings
292
293
Common key constants and platform-specific mappings:
294
295
```typescript { .api }
296
type Key =
297
| "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
298
| "Power" | "Eject" | "Abort" | "Help" | "Backspace" | "Tab"
299
| "Numlock" | "Scrolllock" | "Delete" | "Escape" | "F1" | "F2"
300
| "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10"
301
| "F11" | "F12" | "F13" | "F14" | "F15" | "F16" | "F17" | "F18"
302
| "F19" | "F20" | "F21" | "F22" | "F23" | "F24" | "Digit0"
303
| "Digit1" | "Digit2" | "Digit3" | "Digit4" | "Digit5" | "Digit6"
304
| "Digit7" | "Digit8" | "Digit9" | "KeyA" | "KeyB" | "KeyC"
305
| "KeyD" | "KeyE" | "KeyF" | "KeyG" | "KeyH" | "KeyI" | "KeyJ"
306
| "KeyK" | "KeyL" | "KeyM" | "KeyN" | "KeyO" | "KeyP" | "KeyQ"
307
| "KeyR" | "KeyS" | "KeyT" | "KeyU" | "KeyV" | "KeyW" | "KeyX"
308
| "KeyY" | "KeyZ" | "Semicolon" | "Equal" | "Comma" | "Minus"
309
| "Period" | "Slash" | "Backquote" | "BracketLeft" | "Backslash"
310
| "BracketRight" | "Quote" | "Altleft" | "Altright" | "CapsLock"
311
| "ControlLeft" | "MetaLeft" | "ShiftLeft" | "ControlRight"
312
| "MetaRight" | "ShiftRight" | "ContextMenu" | "Enter" | "Space"
313
| "ArrowDown" | "ArrowLeft" | "ArrowRight" | "ArrowUp" | "End"
314
| "Home" | "Insert" | "PageDown" | "PageUp" | "PrintScreen"
315
| "NumpadDivide" | "NumpadMultiply" | "NumpadSubtract"
316
| "NumpadAdd" | "NumpadEnter" | "NumpadDecimal" | "Numpad0"
317
| "Numpad1" | "Numpad2" | "Numpad3" | "Numpad4" | "Numpad5"
318
| "Numpad6" | "Numpad7" | "Numpad8" | "Numpad9" | "Copy"
319
| "Cut" | "Paste" | "AudioVolumeMute" | "AudioVolumeDown"
320
| "AudioVolumeUp" | "MediaTrackNext" | "MediaTrackPrevious"
321
| "MediaStop" | "MediaPlayPause" | "BrowserSearch" | "BrowserHome"
322
| "BrowserBack" | "BrowserForward" | "BrowserRefresh"
323
| "BrowserStop" | "BrowserFavorites" | "LaunchApplication1"
324
| "LaunchApplication2" | "LaunchMail" | "LaunchMediaPlayer";
325
326
interface USKeyboardLayout {
327
[key: string]: {
328
keyCode: number;
329
shiftKeyCode?: number;
330
key: string;
331
shiftKey?: string;
332
code: string;
333
text?: string;
334
shiftText?: string;
335
location?: number;
336
};
337
}
338
```
339
340
**Usage Examples:**
341
342
```typescript
343
// Using key constants
344
await keyboard.press("Enter");
345
await keyboard.press("ArrowDown");
346
await keyboard.press("F1");
347
await keyboard.press("ControlLeft");
348
349
// Key combinations with proper timing
350
await keyboard.down("ShiftLeft");
351
await keyboard.press("KeyA"); // Capital A
352
await keyboard.up("ShiftLeft");
353
354
// Platform-specific shortcuts
355
const isMac = process.platform === "darwin";
356
const cmdOrCtrl = isMac ? "MetaLeft" : "ControlLeft";
357
358
await keyboard.down(cmdOrCtrl);
359
await keyboard.press("KeyC"); // Copy
360
await keyboard.up(cmdOrCtrl);
361
362
await keyboard.down(cmdOrCtrl);
363
await keyboard.press("KeyV"); // Paste
364
await keyboard.up(cmdOrCtrl);
365
```
366
367
### Advanced Input Scenarios
368
369
Complex input scenarios and best practices:
370
371
```typescript { .api }
372
interface AdvancedInputScenarios {
373
/** Simulate realistic typing with human-like delays */
374
humanType(text: string, options?: HumanTypeOptions): Promise<void>;
375
/** Simulate form filling with tab navigation */
376
fillForm(fields: FormField[]): Promise<void>;
377
/** Simulate file drag and drop */
378
dragDropFile(filePath: string, target: ElementHandle): Promise<void>;
379
/** Simulate drawing/signature input */
380
drawPath(points: Point[], options?: DrawOptions): Promise<void>;
381
}
382
383
interface HumanTypeOptions {
384
/** Base delay between keystrokes */
385
baseDelay?: number;
386
/** Random delay variation */
387
variation?: number;
388
/** Typing mistakes probability */
389
mistakeRate?: number;
390
}
391
392
interface FormField {
393
selector: string;
394
value: string;
395
type?: "text" | "email" | "password" | "number";
396
}
397
398
interface Point {
399
x: number;
400
y: number;
401
}
402
403
interface DrawOptions {
404
pressure?: number;
405
smooth?: boolean;
406
delay?: number;
407
}
408
```
409
410
**Usage Examples:**
411
412
```typescript
413
// Realistic human typing
414
async function humanType(page: Page, selector: string, text: string) {
415
await page.focus(selector);
416
417
for (let i = 0; i < text.length; i++) {
418
const char = text[i];
419
const delay = Math.random() * 100 + 50; // 50-150ms random delay
420
421
await page.keyboard.type(char);
422
await page.waitForTimeout(delay);
423
424
// Occasionally make a mistake and correct it
425
if (Math.random() < 0.05) { // 5% mistake rate
426
await page.keyboard.press("Backspace");
427
await page.waitForTimeout(200);
428
await page.keyboard.type(char);
429
}
430
}
431
}
432
433
// Form automation with tab navigation
434
async function fillFormWithTabs(page: Page) {
435
const fields = [
436
{ selector: "#firstName", value: "John" },
437
{ selector: "#lastName", value: "Doe" },
438
{ selector: "#email", value: "john.doe@example.com" },
439
{ selector: "#phone", value: "555-0123" }
440
];
441
442
await page.focus(fields[0].selector);
443
444
for (const field of fields) {
445
await page.keyboard.type(field.value);
446
await page.keyboard.press("Tab");
447
await page.waitForTimeout(200);
448
}
449
}
450
451
// Signature/drawing simulation
452
async function drawSignature(page: Page, canvasSelector: string) {
453
const canvas = await page.$(canvasSelector);
454
if (!canvas) return;
455
456
const box = await canvas.boundingBox();
457
if (!box) return;
458
459
const startX = box.x + 50;
460
const startY = box.y + box.height / 2;
461
462
// Draw a simple signature curve
463
await page.mouse.move(startX, startY);
464
await page.mouse.down();
465
466
for (let i = 0; i <= 100; i++) {
467
const x = startX + i * 2;
468
const y = startY + Math.sin(i * 0.1) * 20;
469
await page.mouse.move(x, y);
470
await page.waitForTimeout(10);
471
}
472
473
await page.mouse.up();
474
}
475
476
// File drag and drop simulation
477
async function simulateFileDrop(page: Page, filePath: string, dropSelector: string) {
478
const dropZone = await page.$(dropSelector);
479
if (!dropZone) return;
480
481
const box = await dropZone.boundingBox();
482
if (!box) return;
483
484
// Simulate drag and drop events
485
const fileInput = await page.evaluateHandle(() => {
486
const input = document.createElement('input');
487
input.type = 'file';
488
input.style.display = 'none';
489
document.body.appendChild(input);
490
return input;
491
});
492
493
await fileInput.uploadFile(filePath);
494
495
await page.evaluate((input, dropZone) => {
496
const file = input.files[0];
497
const dt = new DataTransfer();
498
dt.items.add(file);
499
500
const dragEvent = new DragEvent('drop', {
501
dataTransfer: dt,
502
bubbles: true,
503
cancelable: true
504
});
505
506
dropZone.dispatchEvent(dragEvent);
507
}, await fileInput.asElement(), await dropZone.asElement());
508
}
509
```
510
511
### Error Handling
512
513
Common input-related errors and handling strategies:
514
515
```typescript { .api }
516
class InputError extends Error {
517
constructor(message: string);
518
}
519
520
class KeyboardError extends InputError {
521
constructor(message: string);
522
}
523
524
class MouseError extends InputError {
525
constructor(message: string);
526
}
527
```
528
529
**Usage Examples:**
530
531
```typescript
532
// Safe input operations
533
async function safeType(page: Page, selector: string, text: string) {
534
try {
535
await page.waitForSelector(selector, { timeout: 5000 });
536
await page.focus(selector);
537
await page.keyboard.type(text);
538
return true;
539
} catch (error) {
540
console.log(`Failed to type in ${selector}:`, error.message);
541
return false;
542
}
543
}
544
545
// Retry mechanism for flaky inputs
546
async function retryClick(page: Page, x: number, y: number, maxRetries = 3) {
547
for (let i = 0; i < maxRetries; i++) {
548
try {
549
await page.mouse.click(x, y);
550
return true;
551
} catch (error) {
552
console.log(`Click attempt ${i + 1} failed:`, error.message);
553
if (i === maxRetries - 1) throw error;
554
await page.waitForTimeout(1000);
555
}
556
}
557
return false;
558
}
559
```