WebRTC fingerprinting reads your codec list and SDP offer, not your IP. Learn how it works, how it differs from a WebRTC leak, and how to reduce it.
WebRTC fingerprinting identifies your browser by reading the list of audio/video codecs it supports and the exact structure of the SDP (Session Description Protocol) text it generates to negotiate a call — not by touching your IP address at all. A script can call a single static method, get back a structured list of codecs and header extensions, and use the shape of that list to help tell browsers, engines, and platforms apart. This is a completely different mechanism from the well-known WebRTC IP leak, and mixing the two up leads to a false sense of security: fixing one does nothing for the other.
Key Takeaways
- WebRTC fingerprinting reads codec support and SDP structure — it never touches your public or local IP address, so it is unrelated to the classic WebRTC leak.
- The core signal comes from
RTCRtpSender.getCapabilities(), a static method that returns your supported codecs with zero permission prompt and zero network traffic. - The SDP text produced by
createOffer()adds a second layer: payload-type numbering, codec ordering, and per-codec parameters likeprofile-level-idorpacketization-mode. - On its own the signal is coarse — it mostly separates browser engine, version, and platform rather than uniquely identifying one person — but it adds a stacking layer alongside canvas, WebGL, and audio fingerprints.
- Disabling WebRTC entirely removes the surface; browser updates and OS-level hardware codec support are the main things that shift the value over time.
What Is WebRTC Fingerprinting?
Every browser that implements WebRTC ships a specific set of audio and video codecs, in a specific order, with specific parameters. Chromium-based browsers, Firefox, and Safari each build on a different underlying media stack, so the exact codec list — and which codecs get hardware acceleration on a given OS — varies between them. A script can read that list directly, or trigger the browser into producing an SDP offer, and use either one as a device/browser signal.
Crucially, this is not the same category of risk as the WebRTC IP leak, where the ICE/STUN process can expose your real public IP even behind a VPN. Codec and SDP fingerprinting reveals what your browser is, not where you are. You can have zero WebRTC leak (a fully proxied, well-configured VPN) and still expose a completely ordinary codec fingerprint, and vice versa.
Reading Codec Capabilities Without a Connection
The simplest and quietest technique doesn't even require creating a peer connection. RTCRtpSender.getCapabilities(kind) is a static method — it returns the browser's supported codecs and header extensions immediately, with no permission prompt, no signaling, and no network activity:
function getWebRTCCodecFingerprint() {
if (!window.RTCRtpSender || !RTCRtpSender.getCapabilities) {
return { supported: false };
}
const audio = RTCRtpSender.getCapabilities('audio');
const video = RTCRtpSender.getCapabilities('video');
return {
supported: true,
audioCodecs: audio.codecs.map((c) => c.mimeType),
videoCodecs: video.codecs.map(
(c) => `${c.mimeType}${c.sdpFmtpLine ? ' ' + c.sdpFmtpLine : ''}`
),
headerExtensions: video.headerExtensions.map((h) => h.uri),
};
}
The returned codecs array includes each codec's MIME type, clock rate, channel count, and an optional sdpFmtpLine carrying codec-specific parameters. The headerExtensions array lists supported RTP header extensions (used for things like audio levels and transport-wide congestion control), and their presence and ordering also vary by engine and version.
What Ends Up in the SDP Offer
If a script goes one step further and actually calls createOffer(), the resulting SDP text exposes the same information in a more granular form: payload-type numbers, codec ordering, and per-codec attribute lines. A trimmed, illustrative video section looks like this:
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 102 127
a=rtpmap:96 VP8/90000
a=rtpmap:98 VP9/90000
a=rtpmap:102 H264/90000
a=fmtp:102 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
a=rtpmap:127 AV1/90000
The SDP format itself is a standardized IETF text protocol — the interesting fingerprinting signal isn't the syntax, it's the specific combination of payload-type numbers, codec order, and fmtp parameters your particular browser/OS/version chooses to emit. Two browsers on different platforms rarely reproduce that combination exactly.
Why This Is Different From a WebRTC IP Leak
It's worth being explicit about the boundary, because the two techniques share a codebase (WebRTC) but nothing else:
| WebRTC IP leak | WebRTC codec/SDP fingerprinting | |
|---|---|---|
| What it exposes | Your real public/local IP address | Your browser engine, version, and platform |
| Mechanism | ICE candidate gathering via STUN/TURN | getCapabilities() and/or SDP offer contents |
| Needs a network round-trip? | Yes — talks to a STUN server | No — getCapabilities() is fully local |
| Bypasses a VPN? | Can, if routing leaks outside the tunnel | Not applicable — no location data involved |
| Fix | Restrict/disable WebRTC, or a leak-proof VPN | Disable WebRTC, or reduce codec surface |
If you've already locked down WebRTC leaks, that protects your location — it does nothing about the codec/SDP signal, since getCapabilities() never asks for network access in the first place.
How Distinctive Is This Signal?
Codec and SDP fingerprinting is a comparatively coarse signal. Because Chrome, Edge, Opera, and Brave all sit on the same Chromium/libwebrtc foundation, they tend to report very similar codec lists — the signal mostly separates engine families (Chromium vs. Gecko vs. WebKit) and platforms (which hardware decoders an OS exposes to the browser) rather than picking out one specific person.
| Factor | What it reveals |
|---|---|
| Codec list & order | Rendering engine family and version |
sdpFmtpLine parameters (e.g. H.264 profile-level-id) | Platform media stack and hardware decoder support |
| Header extension list | Engine version, sometimes enabled experimental features |
| Presence of AV1/HEVC | OS and hardware-acceleration capability |
That makes it a modest contributor on its own — similar in spirit to audio fingerprinting: not enough to identify you alone, but another independent bit-contributor that stacks with canvas and WebGL signals to narrow the crowd further.
Media Capabilities Beyond Codecs
A related, separate API worth knowing about is the Media Capabilities API, specifically navigator.mediaCapabilities.decodingInfo(). It isn't part of WebRTC, but it's frequently probed alongside it because it answers a similar question — what can this device's media pipeline actually do — by reporting whether decoding a given codec/resolution/frame-rate combination would be smooth and powerEfficient (i.e., hardware-accelerated). Since hardware acceleration support is tied to the specific GPU and OS media framework, this adds a hardware-flavored signal on top of the software codec list that WebRTC exposes.
Defenses and Their Tradeoffs
| Approach | Effect | Tradeoff |
|---|---|---|
Disable WebRTC (Firefox media.peerconnection.enabled) | Removes both the codec/SDP signal and the IP-leak surface | Breaks in-browser video/voice calls entirely |
| Tor Browser | WebRTC disabled by default | Same functionality loss, but consistent across all Tor users |
| Restrict to a single codec set via extension | Can reduce which codecs get reported | Few mainstream extensions target this specific signal; most focus on the IP leak instead |
| Accept the signal, focus elsewhere | No functionality lost | Codec fingerprinting is a low-value target compared to canvas/WebGL for most threat models |
There isn't a dedicated mainstream toggle for "randomize my codec list" the way there is for canvas or audio farbling, mainly because the signal is coarser and lower-value than those. For most people, the practical takeaway is to treat this as one more input alongside the higher-entropy signals, rather than a battle worth fighting on its own.
How to Check Your Own Signal
You can see what your own browser exposes without writing any code:
- Run BrowserInsight's fingerprint check to see your combined fingerprint profile, including how much of your overall uniqueness comes from lower-entropy contributors like this one.
- Open your browser's developer console and run the
getWebRTCCodecFingerprint()snippet above to see your raw codec list. - Compare the same test across Chrome, Firefox, and Safari on one machine — the codec order and
fmtpparameters typically differ between engines even on identical hardware. The EFF's Cover Your Tracks project is a good complementary check for how your overall configuration compares to others.
Frequently Asked Questions
Does WebRTC fingerprinting expose my IP address?
No. Codec and SDP fingerprinting reads what your browser supports, using RTCRtpSender.getCapabilities() or the contents of an SDP offer — neither touches your network address. IP exposure is a separate mechanism (the WebRTC leak) covered in our WebRTC leak protection guide.
Does disabling WebRTC fix both the leak and the fingerprint?
Yes — disabling WebRTC entirely (or using a browser like Tor that disables it by default) removes both surfaces at once, since neither getCapabilities() nor SDP negotiation can run without WebRTC enabled. The tradeoff is that in-browser video/voice calling stops working.
Is codec fingerprinting as identifying as canvas or WebGL fingerprinting?
No, it's generally weaker. Because major Chromium-based browsers share the same underlying libwebrtc stack, their codec lists look similar, so the signal mostly reveals engine family and platform rather than pinpointing an individual. It still adds to the overall entropy stack, just less than rendering-based signals.
Can a website read my codec list without asking permission?
Yes. RTCRtpSender.getCapabilities() is a static method that runs with no camera/microphone permission prompt and no network request — it simply reports what the browser's WebRTC implementation supports.
Conclusion
WebRTC fingerprinting and the WebRTC IP leak both live inside the same API, but they expose completely different things: one reveals your real network address, the other reveals your browser engine, version, and platform through codec support and SDP structure. Neither fix substitutes for the other. On its own, codec/SDP fingerprinting is a modest, coarse-grained signal — but understanding it means you won't mistake a leak-proof VPN setup for a fingerprint-proof one.
Recommended Reading:


