MSEdgeExplainers

Web Haptics API

Authors: Nesh Gandhe, Limin Zhu

Status of this Document

This document is a starting point for engaging the community and standards bodies in developing collaborative solutions fit for standardization. The API is in the early ideation and interest-gauging stage, and the solution/design will likely evolve over time.

Table of Contents

  1. Introduction
  2. User-Facing Problem
  3. Goals
  4. Non-goals
  5. Proposed Approach
  6. Sample code
  7. Alternatives Considered
  8. Accessibility, Internationalization, Privacy, and Security Considerations
  9. Reference for Relevant Haptics APIs
  10. Open Questions
  11. Stakeholder Feedback / Opposition
  12. References & Acknowledgements

Introduction

Modern operating systems have embraced haptics as a core part of user experience — providing subtle, low-latency tactile cues that reinforce visual and auditory feedback. These signals improve confidence, precision, and delight in everyday interactions. The Web Haptics API proposes a semantic, cross-platform interface that connects web applications to native haptic capabilities. By focusing on intent-driven effects, the API enables web apps to deliver tactile feedback consistent with OS design principles and native experiences, while preserving and protecting user privacy and security.

An example scenario this proposal aims to support is dragging elements/windows to a snap point. This will enable a much more engaging and satisfying experience for end users.

User-Facing Problem

The navigator.vibrate() API exists today to allow basic or developer-defined-patterned haptics. However, the current API is mobile-centric and lacks engine and device support. It is also coarse-grained and requires the developer to manually program the pattern which can be very confusing.

Goals

Non-goals

Proposed Approach

The Web Haptics API uses a pre-defined list of effects with an optional intensity parameter, without exposing raw waveform authoring or low-level parameters like duration, sharpness, or ramp. Developers request a named effect, and the user agent maps it to the closest native capability (which may be a generic pattern if OS or hardware support is lacking). In order to minimize fingerprinting risks, the API does not currently allow developers to query haptics-capable hardware or available waveforms. Instead, haptics will be sent to the last input device if haptics-capable. The API is not gated behind permission but requires sticky user activation.

navigator.playHaptics(effect, intensity);

The parameters for navigator.playHaptics:

The API always returns undefined. No haptics is played if the last input device is not haptics-capable.

Sample code

<html>
   <head>
      <style>
         #target {
            width: 120px;
            height: 120px;
            background: #4caf50;
            border-radius: 8px;
            position: absolute;
            top: 200px;
            left: 200px;
         }
         #draggable {
            width: 100px;
            height: 100px;
            background: #2196f3;
            border-radius: 8px;
            position: absolute;
            top: 40px;
            left: 40px;
            cursor: grab;
            touch-action: none;
         }
      </style>
   </head>
   <body>
      <div id="target"></div>
      <div id="draggable" draggable="true"></div>
      <script>
         const draggable = document.getElementById('draggable');
         const target = document.getElementById('target');
         let offsetX = 0, offsetY = 0;
         let snapped = false;

         draggable.addEventListener('pointerdown', e => {
            offsetX = e.clientX - draggable.offsetLeft;
            offsetY = e.clientY - draggable.offsetTop;
            draggable.setPointerCapture(e.pointerId);
         });

         draggable.addEventListener('pointermove', e => {
            if (!draggable.hasPointerCapture(e.pointerId)) return;
            draggable.style.left = `${e.clientX - offsetX}px`;
            draggable.style.top = `${e.clientY - offsetY}px`;
            checkSnap();
         });

         function checkSnap() {
            const dRect = draggable.getBoundingClientRect();
            const tRect = target.getBoundingClientRect();
            const distance = Math.hypot(
               dRect.left - tRect.left,
               dRect.top - tRect.top
            );
            const SNAP_DISTANCE = 40;
            if (!snapped && distance < SNAP_DISTANCE) {
               snapped = true;
               // Snap the item visually
               draggable.style.left = `${tRect.left}px`;
               draggable.style.top = `${tRect.top}px`;
               // Trigger the haptic feedback
               if (navigator.playHaptics) {
                  navigator.playHaptics('align', 1);
               }
            } else if (snapped && distance >= SNAP_DISTANCE) {
               snapped = false;
            }
         }
      </script>
   </body>
</html>

Alternatives considered

Given this is an early brainstorming explainer, the API shape is very much open to change and we welcome feedback to ask us to revisit below and other alternatives.

Accessibility, Internationalization, Privacy, and Security Considerations

Privacy

The current design does not expose means to query haptics-capable devices, available waveforms/effects, or success in playing haptics.

Security

The current design does not include permission gate for haptics but requires sticky user activation. While there is potential concern for haptics abuse, this is manageable given -

Reference for relevant haptics APIs

This section provides reference to existing web and native haptics API to help inform the API design and platform supportability.

Known platform-specific native haptics API:

Relevant web APIs:

Open Questions

Stakeholder Feedback / Opposition

We have heard some early developer interest such as dragging divider to a snap point in Slack.

We intend to seek feedback via:

References & acknowledgements

We acknowledge that this design will change and improve through input from browser vendors, standards bodies, accessibility advocates, and developers. Ongoing collaboration is essential to ensure the API meets diverse needs.

We only get here through the contributions of many—thank you to everyone who shares feedback and helps shape this work. Special thanks to: