microsoft/playwright · error · Error
Mouse wheel is not supported in mobile WebKit
Error message
Mouse wheel is not supported in mobile WebKit
What it means
WK mouse input does not support wheel events when the context is emulated as mobile (hasTouch/isMobile => isMobile option). The wheel() method short-circuits before dispatching because mobile WebKit touch scrolling semantics conflict with synthetic wheel dispatch.
Source
Thrown at packages/playwright-core/src/server/webkit/wkInput.ts:157
clickCount
}));
}
async up(progress: Progress, x: number, y: number, button: types.MouseButton, buttons: Set<types.MouseButton>, modifiers: Set<types.KeyboardModifier>, clickCount: number): Promise<void> {
await progress.race(this._pageProxySession.send('Input.dispatchMouseEvent', {
type: 'up',
button,
buttons: toButtonsMask(buttons),
x,
y,
modifiers: toModifiersMask(modifiers),
clickCount
}));
}
async wheel(progress: Progress, x: number, y: number, buttons: Set<types.MouseButton>, modifiers: Set<types.KeyboardModifier>, deltaX: number, deltaY: number): Promise<void> {
if (this._page?.browserContext._options.isMobile)
throw new Error('Mouse wheel is not supported in mobile WebKit');
await progress.race(this._session!.send('Page.updateScrollingState'));
// Wheel events hit the compositor first, so wait one frame for it to be synced.
await this._page!.mainFrame().evaluateExpression(progress, `new Promise(requestAnimationFrame)`, { world: 'utility' });
await progress.race(this._pageProxySession.send('Input.dispatchWheelEvent', {
x,
y,
deltaX,
deltaY,
modifiers: toModifiersMask(modifiers),
}));
}
setPage(page: Page) {
this._page = page;
}
}
export class RawTouchscreenImpl implements input.RawTouchscreen {View on GitHub (pinned to c8fc3bf8d3)
Solutions
- Drop isMobile from context options (or use a non-mobile device descriptor) if you need wheel events.
- For mobile emulation, scroll via touch-based APIs (e.g. page.touchscreen.tap/swipe patterns or evaluate window.scrollBy) instead of mouse.wheel.
- Branch test logic on the emulation mode: wheel for desktop, touch-scroll for mobile.
Example fix
// before
const ctx = await browser.newContext({ ...devices['iPhone 13'] });
await page.mouse.wheel(0, 500); // throws
// after
await page.evaluate(y => window.scrollBy(0, y), 500); Defensive patterns
Strategy: validation
Validate before calling
function supportsWheel(contextOptions) { return !contextOptions.isMobile; }
if (supportsWheel(ctxOptions)) await page.mouse.wheel(0, 500);
else await page.evaluate(y => window.scrollBy(0, y), 500); Type guard
function isMobileContext(opts: { isMobile?: boolean }): boolean { return !!opts.isMobile; } Try / catch
try { await page.mouse.wheel(0, 500); }
catch (e) {
if (/mobile WebKit/.test(e.message)) await page.evaluate(y => window.scrollBy(0, y), 500);
else throw e;
} Prevention
- Don't combine mobile device descriptors with mouse.wheel.
- Branch scroll strategy on emulation mode.
When it happens
Trigger: Calling page.mouse.wheel(...) (or locator/keyboard-driven scroll-by-wheel) on a context launched with isMobile:true or a device descriptor setting isMobile. Also via tools that synthesize wheel for scrolling.
Common situations: Using a mobile device descriptor (iPhone/Pixel presets set isMobile) and then attempting page.mouse.wheel. Mixing desktop scroll idioms into mobile emulation tests.
Related errors
- Unknown button: ${button}
- WebKit on Windows has a minimal viewport of 250x240.
- Invalid timezone ID: ${contextOptions.timezoneId}
- Unknown permission: ${permission}
- "isMobile" option is not supported with null "viewport"
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/2db04f534818f1f1.
Report an issue: GitHub.