{"record":{"id":"2a141832d814c95d","repo":"microsoft/playwright","slug":"hastouch-must-be-enabled-on-the-browser-context-be","errorCode":null,"errorMessage":"hasTouch must be enabled on the browser context before using the touchscreen.","messagePattern":"hasTouch must be enabled on the browser context before using the touchscreen\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/input.ts","lineNumber":372,"sourceCode":"  return result;\n}\n\nexport interface RawTouchscreen {\n  tap(progress: Progress, x: number, y: number, modifiers: Set<types.KeyboardModifier>): Promise<void>;\n}\n\nexport class Touchscreen {\n  private _raw: RawTouchscreen;\n  private _page: Page;\n\n  constructor(raw: RawTouchscreen, page: Page) {\n    this._raw = raw;\n    this._page = page;\n  }\n\n  async apiTap(progress: Progress, x: number, y: number) {\n    if (!this._page.browserContext._options.hasTouch)\n      throw new Error('hasTouch must be enabled on the browser context before using the touchscreen.');\n    await this._page.instrumentation.onBeforeInputAction(progress, this._page, { x, y });\n    await this.tap(progress, x, y);\n  }\n\n  async tap(progress: Progress, x: number, y: number) {\n    await this._raw.tap(progress, x, y, this._page.keyboard._modifiers());\n  }\n}\n","sourceCodeStart":354,"sourceCodeEnd":381,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/input.ts#L354-L381","documentation":"Thrown by Touchscreen.apiTap() when the browser context was not created with hasTouch: true. This is the same constraint as Frame.tap() but enforced at the Touchscreen API level. The touchscreen object requires touch event emulation, which is a context-level option that cannot be toggled per-page or per-action.","triggerScenarios":"Calling page.touchscreen.tap(x, y) on a page whose context was created with default options (hasTouch is false). This is distinct from Frame.tap() in that it taps raw coordinates rather than a selector, but the underlying touch emulation requirement is identical.","commonSituations":"Test code accesses page.touchscreen directly for coordinate-based taps without enabling hasTouch on the context. Reusing a desktop context fixture for a test that calls touchscreen.tap(). Porting code from a mobile test suite to a shared context without updating context options.","solutions":["Create the browser context with hasTouch: true: const context = await browser.newContext({ hasTouch: true }).","Use a device descriptor that includes hasTouch: const context = await browser.newContext({ ...devices['iPhone 13'] }).","Use page.mouse.click(x, y) instead of page.touchscreen.tap(x, y) if touch emulation is not needed."],"exampleFix":"// before\nconst context = await browser.newContext();\nconst page = await context.newPage();\nawait page.touchscreen.tap(100, 200); // throws [333]\n\n// after\nconst context = await browser.newContext({ hasTouch: true });\nconst page = await context.newPage();\nawait page.touchscreen.tap(100, 200);","handlingStrategy":"validation","validationCode":"const context = await browser.newContext({ hasTouch: true });\n// touchscreen.tap is now safe to use","typeGuard":"function contextSupportsTouch(context: import('@playwright/test').BrowserContext): boolean {\n  return (context.options() as any).hasTouch === true;\n}","tryCatchPattern":null,"preventionTips":["Create context with { hasTouch: true } before using touchscreen APIs.","Use device descriptors that include hasTouch for mobile emulation.","Use page.mouse.click() if touch emulation is not needed."],"tags":["touchscreen","touch","hastouch","context-options","input"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}