Open-source project
pion/webrtc avatar
pion/webrtc

pion/webrtc: a pure Go WebRTC stack you embed in your own server

Pure Go implementation of the WebRTC API

16,813 stars1,895 forksGoMIT

At a glance

What is it?
Pion WebRTC implements the browser WebRTC API in Go, so a Go process can be the peer instead of a browser. It suits media servers, SFUs and data-channel relays, and it is a poor fit if you wanted a drop-in video calling product.
Who is it for?
Adopt pion/webrtc when the peer on one side of the connection is a Go process you control: an SFU, a recording service, a robot, or a data-channel relay between servers. Do not adopt it expecting a finished conferencing product, a signalling server, or browser-side JavaScript, because the repository ships none of those.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why a Go process would want to be a WebRTC peer

Browsers speak WebRTC natively. Servers historically did not, which pushed media handling into native libraries with C bindings, or into a browser instance running headless. Pion WebRTC removes that constraint by implementing the WebRTC API in Go, so the far end of a peer connection can be an ordinary Go binary. The README lists the intended shapes directly: sending a video file to several browsers in sync, streaming a webcam from an embedded device to a browser with no extra server, moving data between two servers without pub/sub, and running server-side effects on incoming media.

The audience is therefore Go engineers building infrastructure, not application developers looking for a calling widget. If your product is a video meeting, you would normally reach for a hosted service or a complete SFU. Pion gives you the peer connection, ICE, DTLS, SRTP and SCTP plumbing, and expects you to supply signalling, room state, and the media pipeline decisions.

What sits inside the module: ICE, DTLS, SRTP, SCTP

The go.mod file shows the architecture more clearly than prose does. pion/webrtc/v4 depends on pion/ice/v4 for connectivity, pion/dtls/v3 for the handshake, pion/srtp/v3 for media encryption, pion/sctp and pion/datachannel for data channels, pion/rtp and pion/rtcp for packet handling, pion/sdp/v3 for session description parsing, and pion/interceptor for the processing chain. The top-level repository is largely the glue that presents these as the PeerConnection API described in the W3C webrtc-pc specification.

That layering is the practical point. Each layer is a separate module you can also use on its own, and the interceptor package is where NACK, sender and receiver reports, and transport-wide congestion control feedback live, rather than being hardcoded into the peer connection. The API also exposes direct RTP and RTCP access, and the README notes that a developer can supply their own packetizer instead of the built-in Opus, PCM, H264, VP8 and VP9 ones. Container support for IVF, Ogg, H264 and Matroska is provided for sending and saving media.

Connectivity features include a full ICE agent, ICE restart, trickle ICE, STUN, TURN over UDP, TCP, DTLS and TLS, and mDNS candidates. Data channels can be ordered or unordered, lossy or lossless. On the security side the README names TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 and TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA for DTLS v1.2, and SRTP_AEAD_AES_256_GCM and SRTP_AES128_CM_HMAC_SHA1_80 for SRTP, with hardware acceleration available for the GCM suites.

Installing pion/webrtc and opening a first data channel

Go modules are mandatory, and the README is explicit that you must specify the version suffix when importing. Set the module mode and pull the package:

bash
export GO111MODULE=on
go get github.com/pion/webrtc/v4

The import path carries /v4, so a file that imports the bare github.com/pion/webrtc path will not resolve against this release line. Your toolchain also has to satisfy the go 1.24.0 directive recorded in go.mod.

Once the module is in place, the smallest useful program creates a peer connection and registers a data channel handler. Rather than a fragment written from memory, the repository ships runnable programs for exactly this: examples/data-channels-simple, examples/data-channels, examples/data-channels-detach, examples/data-channels-detach-create, examples/data-channels-flow-control and examples/data-channels-whip-whep-like. Read the one closest to your case and run it from the examples directory. The API surface mirrors the browser names, so the calls read as the JavaScript equivalents in Go.

What you should see is a process that stays alive with a peer connection object and no media flowing yet. Nothing happens until you exchange session descriptions and ICE candidates with another peer. That exchange is signalling, and Pion does not provide it. Beyond the data-channel programs, examples/pion-to-pion, examples/ice-restart, examples/ice-tcp, examples/ice-single-port, examples/play-from-disk, examples/play-from-disk-renegotiation, examples/simulcast, examples/broadcast and examples/insertable-streams cover the rest of the common ground.

Signalling, NAT and the parts Pion leaves to you

The most common misreading of this project is expecting it to be a server. It is a library. Peer connections need an out-of-band channel to swap SDP offers and answers and ICE candidates, and the README says nothing about providing one. You build it, over WebSocket, HTTP, a message queue, or anything else. Teams that arrive expecting a signalling endpoint will spend their first week writing one.

NAT traversal is the second boundary. Pion implements the ICE agent and can talk to STUN and TURN servers, but it does not run them. In a network where both peers sit behind symmetric NAT, you need a TURN server you operate or pay for, and that server carries the media. The README lists TURN support over UDP, TCP, DTLS and TLS, which tells you the client side is covered, not that infrastructure is included.

The pure Go claim has one documented exception worth knowing before you design around it. The README states that the getUserMedia implementation lives in the separate pion/mediadevices repository and requires Cgo. So the core library builds without Cgo across Windows, macOS, Linux, FreeBSD, iOS, Android, WASM, and the 386, amd64, arm, mips and ppc64 architectures, but camera capture on the host is not part of that clean build story.

Where pion/webrtc is the wrong tool

If you want a video call in a web page, this is the wrong layer. There is no browser bundle, no UI, and no room concept. The JavaScript in the repository is test tooling: package.json declares a private package whose only dev dependency is @roamhq/wrtc, used to exercise the Go code against a Node WebRTC implementation.

If your team is not writing Go, the cost is steep. The API is idiomatic Go with callbacks and channels, and the value comes from embedding it in a Go service. Wrapping it for another language means reimplementing the parts you actually wanted.

There is also a real operational cost in the media path. Choosing your own packetizer or reading raw RTP means you own jitter, packet loss handling and congestion response. The interceptor package gives you building blocks such as NACK and transport-wide congestion control feedback, and the bandwidth-estimation-from-disk example shows the shape of an estimation loop, but assembling those into something that behaves well on a bad mobile network is engineering work, not configuration.

How this differs from a WebSocket-based media path

The alternative people most often weigh is sending media over WebSockets, or using a managed WebRTC platform. The difference is not stylistic. A WebSocket is a reliable, ordered, TCP-backed stream: one lost packet stalls everything behind it, which is exactly the behaviour you do not want for live audio and video. Pion's media path runs over SRTP on top of DTLS over UDP, with RTCP feedback for loss and congestion, and it can also carry unreliable, unordered data channels over SCTP for cases where you want datagram semantics without media.

Managed platforms take the opposite trade. You get signalling, TURN, recording and dashboards, and you give up control of the media path and the deployment shape. Pion inverts that: you own the pipeline and the infrastructure, and you get to run the peer inside a Go process on your own hardware, including embedded devices and WASM targets. For a data-channel relay between two backend services, where there is no browser at all, that inversion is the whole reason to pick it.

Release cadence, licence and upgrade cost

The repository is not archived, and the last push was on 2026-09-20. Releases are frequent and small: v4.2.20 on 2026-09-04, v4.2.19 on 2026-08-27, v4.2.18 on 2026-07-27. Patch-level upgrades inside v4 are the normal path.

The larger cost sits at the major boundary. The README points to the v4.0.0 release notes on the wiki for new features and breaking changes, and tells anyone who cannot upgrade yet to use the latest v3 tag. If you are on v3, budget for the migration rather than assuming a version bump.

Licensing is MIT, and the repository carries a LICENSES directory alongside the LICENSE file, which suggests per-file licence tracking. MIT is permissive and imposes no source disclosure on your application. The dependency graph is a second consideration: pion/webrtc/v4 pulls in roughly a dozen pion modules plus golang.org/x/net and, indirectly, golang.org/x/crypto. None of that changes the MIT terms of the top-level module, but your own dependency review should cover the whole set. This is not legal advice; check your organisation's policy.

Editorial conclusion

Adopt pion/webrtc when the peer on one side of the connection is a Go process you control: an SFU, a recording service, a robot, or a data-channel relay between servers. Do not adopt it expecting a finished conferencing product, a signalling server, or browser-side JavaScript, because the repository ships none of those. Before committing, verify the codec and interceptor coverage your workload needs against the examples directory, confirm your toolchain satisfies the go 1.24.0 directive in go.mod, and read the v4.0.0 release notes on the wiki for the breaking changes that separate v3 from v4.

Frequently asked questions

Is pion/webrtc better than WebSockets for sending media?

They solve different problems. WebSockets give you a reliable, ordered stream over TCP, while pion/webrtc runs media over SRTP on UDP with RTCP feedback for loss and congestion, and can carry unreliable, unordered data channels over SCTP. For live audio and video, the WebRTC path is the one designed for it.

Which browsers support WebRTC?

The README does not enumerate browser support. Pion implements the WebRTC API in Go for the server side, and the repository's browser-facing testing uses a Node WebRTC implementation rather than a list of supported browsers.

How do I install pion/webrtc in a Go project?

Go modules are mandatory. Set GO111MODULE=on and run go get github.com/pion/webrtc/v4, then import the path with the /v4 suffix. Your toolchain must satisfy the go 1.24.0 directive in go.mod.

Official sources

  1. License: MIT
  2. pion/webrtc on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pion-webrtc.svg)](https://hysenlabs.com/projects/pion-webrtc)