Noureddine RAMDI / Intercept and replace WebRTC streams with pion/handoff: a hands-on look

Created Mon, 04 May 2026 10:23:03 +0000 Modified Sat, 23 May 2026 20:41:27 +0000

pion/handoff

Intercepting WebRTC sessions in real time and swapping out a browser’s webcam feed for an arbitrary video source sounds like a hack on steroids. Yet that’s exactly what pion/handoff achieves by transparently mocking the RTCPeerConnection API in the browser and forwarding the signaling to a custom backend. This enables a man-in-the-middle setup for WebRTC traffic where media streams can be recorded, replaced, or analyzed without the remote peer noticing.

how pion/handoff intercepts and redirects WebRTC sessions

At its core, pion/handoff is a Go-based tool designed to intercept browser WebRTC sessions by overriding the RTCPeerConnection JavaScript API in the browser environment. This is done using a Greasemonkey userscript, which automatically injects code to mock the RTCPeerConnection interface. When a web page tries to create a WebRTC connection, the mocked API forwards all signaling messages (like SDP offers/answers and ICE candidates) to a backend server controlled by you.

The backend then takes over the actual WebRTC connection establishment using Go’s WebRTC implementation. This architecture decouples the browser’s signaling from the peer connection lifecycle, effectively replacing the browser’s native WebRTC connection with one managed server-side.

This setup enables several use cases:

  • Recording media streams: As media passes through the backend, it can be captured and saved for auditing or analysis.
  • Media stream replacement: Instead of using the browser’s camera or microphone, the backend can inject arbitrary media streams, for example, an FFmpeg-generated test video.
  • Traffic analysis and reverse engineering: By capturing decrypted ICE, DTLS, RTP, RTCP, and SCTP packets on the backend, developers can analyze raw WebRTC traffic.

Under the hood, the system relies on:

  • The mocked RTCPeerConnection API on the client side, which hijacks the normal WebRTC signaling flow.
  • A signaling forwarding layer that sends these messages to the backend.
  • The pion/webrtc Go library on the server side, which handles the actual WebRTC session lifecycle.

This combination provides a transparent bridge between the browser and the backend, allowing full control over the media streams.

technical strengths and tradeoffs in pion/handoff’s approach

The standout technical feature is the transparent mocking of the RTCPeerConnection API in the browser. This is not trivial; WebRTC APIs are complex, stateful, and tightly integrated with browser internals. Achieving a mock that forwards all necessary signaling without breaking expected behavior requires deep understanding of the WebRTC spec and browser behavior.

The use of a userscript (Greasemonkey) for injection is a pragmatic choice that gives flexibility without modifying the browser itself or requiring browser extensions. However, this comes with some limitations:

  • Browser compatibility may vary, depending on how well the userscript runs and how the browser exposes WebRTC internals.
  • The approach depends on the web page not using obfuscated or heavily customized WebRTC usage that might bypass or break the mock.
  • There is a security tradeoff: intercepting and redirecting WebRTC sessions requires trust in the backend and userscript, which could be exploited if misused.

On the backend, pion/handoff leverages the pion/webrtc Go library, which is a mature and well-maintained WebRTC implementation. This ensures robust handling of ICE, DTLS, and RTP protocols. The backend architecture allows:

  • Efficient media stream processing and replacement.
  • Access to decrypted media packets for advanced use cases like media saving or traffic analysis.

The tradeoff here is increased complexity and resource usage on the server side, which now handles media streams instead of them flowing peer-to-peer.

The codebase is concise and focused, with examples demonstrating datachannel manipulation, media saving, sending, and userscript generation. This helps developers quickly understand how to customize or extend the tool.

explore the project and get oriented

Since the repository doesn’t provide direct installation or quickstart commands in the README analysis, the best way to start is by exploring the key resources:

  • README.md: The main documentation explains the core concepts, use cases, and provides links to user scripts and examples.

  • userscript/: This directory contains the Greasemonkey userscript that mocks RTCPeerConnection. Reviewing this script helps understand how browser API interception is done.

  • examples/: Contains several example programs demonstrating different use cases:

    • Datachannel manipulation
    • Saving media streams to disk
    • Sending media streams from external sources
    • Userscript generation
  • pkg/handoff/: This package contains the core Go logic for handling signaling forwarding and WebRTC session management.

To experiment, you would:

  1. Inject the userscript into your browser (using Greasemonkey/Tampermonkey).
  2. Run the backend example that suits your use case (e.g., media saving or replacement).
  3. Connect to a WebRTC-enabled web app and observe how the stream is intercepted and handled by the backend.

The examples provide concrete entry points for customization and integration.

verdict: who should look at pion/handoff

pion/handoff is a niche but valuable tool for developers deeply involved in WebRTC internals, media stream manipulation, or real-time communication debugging. If you need to record WebRTC streams server-side, inject custom media in place of browser sources, or analyze raw WebRTC traffic, this repo gives you a solid foundation.

The approach’s main limitation is the reliance on browser API mocking via userscripts, which can be fragile and browser-dependent. This isn’t a turnkey solution for every WebRTC app but a powerful toolkit for experimentation and advanced use cases.

If you work with WebRTC and want to understand or control media streams beyond the usual browser constraints, pion/handoff is worth studying. The code is surprisingly clean for such a complex domain, and the examples provide a good DX for getting started.

For production use, carefully consider security implications and browser compatibility. But as a technical deep dive and practical tool, it’s a rare find in the WebRTC ecosystem that deserves attention.


→ GitHub Repo: pion/handoff ⭐ 189 · Go