{"record":{"id":"013f26df0daeb384","repo":"microsoft/playwright","slug":"the-page-does-not-support-tap-use-hastouch-contex","errorCode":null,"errorMessage":"The page does not support tap. Use hasTouch context option to enable touch support.","messagePattern":"The page does not support tap\\. Use hasTouch context option to enable touch support\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/frames.ts","lineNumber":1295,"sourceCode":"        position: options.sourcePosition,\n      });\n    }));\n    // Note: do not perform locator handlers checkpoint to avoid moving the mouse in the middle of a drag operation.\n    dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, { ...options, performActionPreChecks: false }, async (progress, handle) => {\n      return handle._retryPointerAction(progress, 'move and up', false, async (progress, point) => {\n        await this._page.mouse.move(progress, point.x, point.y, { steps: options.steps });\n        await this._page.mouse.up(progress);\n      }, {\n        ...options,\n        waitAfter: 'disabled',\n        position: options.targetPosition,\n      });\n    }));\n  }\n\n  async tap(progress: Progress, selector: string, options: types.PointerActionWaitOptions) {\n    if (!this._page.browserContext._options.hasTouch)\n      throw new Error('The page does not support tap. Use hasTouch context option to enable touch support.');\n    return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (progress, handle) => handle._tap(progress, options)));\n  }\n\n  async fill(progress: Progress, selector: string, value: string, options: types.CommonActionOptions) {\n    return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (progress, handle) => handle._fill(progress, value, options)));\n  }\n\n  async focus(progress: Progress, selector: string, options: types.StrictOptions & { noAutoWaiting?: boolean }) {\n    dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (progress, handle) => handle._focus(progress)));\n  }\n\n  async blur(progress: Progress, selector: string, options: types.StrictOptions & { noAutoWaiting?: boolean }) {\n    dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (progress, handle) => handle._blur(progress)));\n  }\n\n  async resolveSelector(progress: Progress, selector: string, options: { mainWorld?: boolean } = {}): Promise<{ resolvedSelector: string }> {\n    const element = await progress.race(this.selectors.query(selector, options));\n    if (!element)","sourceCodeStart":1277,"sourceCodeEnd":1313,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/frames.ts#L1277-L1313","documentation":"Thrown by Frame.tap() when the browser context was not created with hasTouch: true. Tap requires touch event emulation which is a context-level setting, not a per-page or per-action setting. The method checks browserContext._options.hasTouch before delegating to the element handle's _tap method.","triggerScenarios":"Calling page.tap(selector) or locator.tap() on a context/page created with the default options (hasTouch defaults to false). Common when test code originally written for a mobile/touch project is run in a standard desktop context without the hasTouch flag.","commonSituations":"Reusing a shared browser context fixture across desktop and mobile test suites without enabling hasTouch. Copying tap-based test code from a mobile emulation example into a standard context. Forgetting to set hasTouch when emulating specific mobile devices with browser.newContext().","solutions":["Create the browser context with hasTouch enabled: const context = await browser.newContext({ hasTouch: true }).","Use page.click() instead of page.tap() if touch emulation is not needed — click works in all contexts.","Use devices descriptors that include hasTouch, e.g., browser.newContext({ ...devices['iPhone 13'] })."],"exampleFix":"// before\nconst context = await browser.newContext();\nawait page.tap('#button'); // throws [323]\n\n// after\nconst context = await browser.newContext({ hasTouch: true });\nconst page = await context.newPage();\nawait page.tap('#button');","handlingStrategy":"validation","validationCode":"const context = await browser.newContext({ hasTouch: true });\n// or validate before tapping\nfunction assertHasTouch(page) {\n  if (!page.context()._options.hasTouch)\n    throw new Error('Enable hasTouch on context before using tap');\n}","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 } when testing touch interactions.","Use device descriptors (e.g., devices['iPhone 13']) which include hasTouch.","Use page.click() instead of page.tap() if touch emulation is unnecessary."],"tags":["tap","touch","hastouch","context-options","frame"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}