Approaches to browser tab sharing with HTML5

True VNC-style screen sharing in the browser is a hard problem. Relaying pointer movement, forwarding keystrokes, and repainting at 60fps push platform APIs to their limits. If you narrow the goal to sharing the contents of a single browser tab, the problem simplifies into two parts: capture the visible page state, and push that frame to viewers. The capture side is the hard half.

Projects like html2canvas work by reimplementing the browser's rendering engine in JavaScript, which is impressive but far too slow for real-time use. Google Feedback is another example, but it isn't open-source. This article looks at several proof-of-concept techniques for tab sharing that take different tradeoffs.

Mutation Observers plus WebSocket

One approach, demonstrated by Rafael Weinstein, pairs Mutation Observers with a WebSocket. The presenter's page watches for DOM changes and sends diffs to the viewer instead of full page snapshots. As the user scrolls or modifies the document, the observer fires and the diff travels over the socket. Because only the changed portions are transmitted, this stays reasonably performant—the entire document isn't resent on every update.

This is explicitly a proof of concept, but it shows how to combine a newer platform feature like Mutation Observers with an older one like WebSockets without drowning the network in redundant data.

Blob clones of the HTMLDocument over a binary socket

Another approach clones the entire HTMLDocument, wraps it in a Blob, and ships it across a binary WebSocket. The steps are straightforward:

  1. Rewrite all URLs on the page to absolute form so static assets and CSS don't break when the snapshot is viewed from a different origin.
  2. Clone the document element with document.documentElement.cloneNode(true).
  3. Set the clone to be read-only and non-interactive with CSS like pointer-events: none, user-select: none, and overflow: hidden.
  4. Record the current scrollX and scrollY values as data-* attributes on the clone.
  5. Build a new Blob() from the clone's outerHTML.

On the viewer side, the blob renders as a snapshot page. To keep the viewer in sync with the presenter's scrolling, a small script is injected into the blob that reads those scroll attributes and positions the page accordingly on load. The illusion is that only a viewport-sized section was captured, when in fact the entire document has been duplicated and scrolled into place behind the viewer's window.

This works as a continuous capture loop if you attach it to a Node WebSocket server and trigger captures from a bookmarklet. It isn't optimized—duplicating the entire document every frame is wasteful, the way the Mutation Observer approach is not. The simplistic URL rewriting also misses relative CSS background images, which is a known gap.

Chrome extension capture with binary WebSockets

The tab capture extension API provides a much cheaper path, though it's not pure HTML5—it depends on a Chrome-specific extension API. The core sequence is:

  • Screenshot the current tab to a PNG dataURL via chrome.tabs.captureVisibleTab().
  • Convert the dataURL to a Blob using a helper like convertDataURIToBlob().
  • Send each Blob as a binary frame over a WebSocket.

The capture side looks like this: grab the visible tab, convert it, and push it over the socket. Performance is surprisingly good for this method. The biggest inefficiency is the dataURL-to-Blob conversion step, since chrome.tabs.captureVisibleTab() returns only a dataURL. If it gave back a Blob or Typed Array, frames could flow straight into the socket with no extra conversion—a feature request tracked at crbug.com/32498.

What comes next: WebRTC tab capture

Long-term, screen sharing belongs to WebRTC. In August 2012 the Chromium team proposed a WebRTC Tab Content Capture API specifically for sharing the contents of a browser tab. Until that lands, the practical options remain the methods above—each of which is a capable demo but short of a polished sharing experience. Mutation Observers give efficient diffs but no bitmap output; the Blob approach is brute-force and wasteful; the extension API is fast but confined to Chrome.

All three prove that today's web platform can handle tab sharing. But none of them yet deliver the full, low-latency, high-fidelity session that a dedicated tab capture API should eventually make possible.