WebRTC Codec Fingerprinting: When Media Capabilities Reveal Your Platform
WebRTC codec enumeration through getCapabilities() and SDP offers exposes hardware-specific media capabilities that differ across operating systems. Learn how codec lists become a platform fingerprint and how to control them.
Introduction
WebRTC enables real-time video and audio communication in the browser. Before any media flows between peers, browsers enumerate their supported codecs and expose them through capability APIs and SDP (Session Description Protocol) offers. This negotiation is essential for functional video calls, but it also creates a detailed inventory of your system's media capabilities that any website can query without special permissions.
WebRTC codec capabilities differ across platforms and can be used as a tracking signal. Different operating systems provide different levels of hardware acceleration support, which directly determines which codecs appear in the browser's capability lists. A website can query these lists and compare them against known platform profiles to infer your real operating system, even when your user agent string claims something different.
BotBrowser addresses this by constructing WebRTC codec capability lists entirely from the fingerprint profile, ensuring that what JavaScript sees matches the profile's target platform rather than the host system's actual hardware.
BotBrowser's Solution
BotBrowser solves WebRTC codec fingerprinting at the browser engine level, where codec capabilities are actually determined. Rather than patching JavaScript APIs or post-processing SDP strings, BotBrowser constructs the codec capability lists from the fingerprint profile data. This ensures that every API that exposes codec information returns consistent, profile-accurate results.
Profile-Driven Codec Construction
When a BotBrowser profile is loaded, the WebRTC codec capabilities are built from the profile's recorded codec data rather than from the host system's actual hardware capabilities. The profile contains the complete codec configuration captured from a real device matching the target platform:
- The full list of supported video and audio codecs
- Codec parameters including profiles, levels, and format-specific options
- The correct ordering of codecs in capability lists
- Payload type assignments for SDP generation
This means that a profile targeting one platform, loaded on a completely different host OS, will still report the correct WebRTC codecs for the profile's target. The host system's actual capabilities are irrelevant to what JavaScript sees.
SDP Consistency
BotBrowser ensures that the SDP generated by createOffer() is consistent with the codec capabilities reported by getCapabilities(). Both are derived from the same profile data, so there is no gap between what the capability APIs report and what appears in the SDP.
The m=video and m=audio lines in the SDP contain exactly the payload types that correspond to the profile's codec set. The a=rtpmap and a=fmtp attributes match the parameters from the capability objects. Any script that queries both APIs and compares them will find perfect consistency.
Functional Compatibility
One of the challenges in controlling WebRTC codecs is maintaining actual media functionality. If the profile specifies a codec that the host system cannot actually decode, the browser needs to handle this gracefully.
BotBrowser addresses this through a dual-layer design: JavaScript sees the profile's codec list, while internally the browser registers only the codecs that the host system can actually process. This separation means:
- Fingerprinting scripts see the profile-accurate codec list.
- Actual WebRTC calls negotiate using codecs that both peers and the local system can handle.
- There is no crash or error when a profile lists a codec that the host cannot decode.
This is a critical distinction. Simply injecting codec entries into the capability list would cause failures when the browser attempts to actually use those codecs. BotBrowser's engine-level integration handles the boundary between fingerprint presentation and functional media processing correctly.
Cross-API Alignment
BotBrowser ensures consistency not just within WebRTC APIs, but across the full set of media capability interfaces:
RTCRtpSender.getCapabilities()andRTCRtpReceiver.getCapabilities()return profile-consistent codecs.- SDP offers from
createOffer()contain matching payload types. - General media APIs like
canPlayType()andMediaCapabilities.decodingInfo()return results that are consistent with the WebRTC codec profile. - The overall media fingerprint tells a single, coherent story about the platform.
This cross-API alignment is what makes BotBrowser's protection effective. All codec-reporting paths are governed by a single, consistent data source: the loaded profile.
Configuration and Usage
Basic CLI Usage
WebRTC codec protection is automatic when a profile is loaded. No additional flags are needed:
chrome --bot-profile="/path/to/profile.enc" \
--user-data-dir="$(mktemp -d)"
The profile's WebRTC codec configuration is applied at startup. All subsequent WebRTC capability queries and SDP generation will reflect the profile's codec set.
Playwright Integration
const { chromium } = require('playwright-core');
(async () => {
const browser = await chromium.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
],
headless: true,
});
const context = await browser.newContext({ viewport: null });
const page = await context.newPage();
await page.goto('about:blank');
// Verify WebRTC codec capabilities from the loaded profile
const codecInfo = await page.evaluate(() => {
const videoCaps = RTCRtpSender.getCapabilities('video');
const audioCaps = RTCRtpSender.getCapabilities('audio');
return {
videoCodecCount: videoCaps?.codecs.length || 0,
audioCodecCount: audioCaps?.codecs.length || 0,
};
});
console.log('Video codecs:', codecInfo.videoCodecCount);
console.log('Audio codecs:', codecInfo.audioCodecCount);
await browser.close();
})();
Puppeteer Integration
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
],
headless: true,
defaultViewport: null,
});
const page = await browser.newPage();
await page.goto('about:blank');
// Verify WebRTC codec capabilities from the loaded profile
const codecs = await page.evaluate(() => {
const videoCaps = RTCRtpSender.getCapabilities('video');
const audioCaps = RTCRtpSender.getCapabilities('audio');
return {
videoCount: videoCaps?.codecs.length || 0,
audioCount: audioCaps?.codecs.length || 0,
};
});
console.log(`Video codecs: ${codecs.videoCount}`);
console.log(`Audio codecs: ${codecs.audioCount}`);
await browser.close();
})();
Combined with Proxy and Platform Settings
For complete platform consistency, combine codec protection with proxy and platform configuration:
chrome --bot-profile="/path/to/profile.enc" \
--proxy-server="socks5://user:pass@proxy.example.com:1080" \
--bot-config-timezone="America/New_York" \
--bot-config-locale="en-US" \
--user-data-dir="$(mktemp -d)"
This ensures that not only are codec capabilities consistent with the profile's platform, but network identity, timezone, locale, and all other signals align as well.
Verification
After configuring BotBrowser with a profile, verify that WebRTC codec protection is working:
-
Codec count check: Call
RTCRtpSender.getCapabilities('video')and confirm the number of codecs matches what you expect for the profile's target platform. -
Stability check: Reload the page and repeat. The codec count and types should be identical across page loads. Restart the browser with the same profile and verify again.
-
Fingerprint testing sites: Visit browser fingerprint testing services and check the WebRTC section. The reported codecs should not flag any anomalies.
Best Practices
-
Always use a complete profile. WebRTC codec capabilities must align with the profile's operating system, browser version, and GPU configuration. BotBrowser profiles are captured from real devices, ensuring that all these dimensions are internally consistent. Do not mix and match profile components.
-
Match codec expectations to your use case. If you are working with websites that actively use WebRTC for video calls or streaming, make sure your profile's codec set supports the formats those sites expect. A profile that excludes commonly used codecs may cause negotiation failures during actual WebRTC sessions.
-
Combine with WebRTC IP protection. Codec fingerprinting and IP leaking are separate WebRTC privacy concerns, but both need to be addressed. Use BotBrowser's proxy integration with
--proxy-serverand--bot-webrtc-iceto ensure that your WebRTC IP addresses are also controlled. See the WebRTC leak prevention guide for details. -
Do not modify codec settings manually. Let the profile handle codec configuration entirely. Manually adding or removing codecs through chrome flags or configuration overrides can create inconsistencies that undermine the profile's consistency.
-
Keep profiles up to date. Codec support changes with browser versions. New codecs are added, and existing codec parameters may change. Using profiles that match the claimed browser version ensures that your codec capabilities correspond to what a real browser of that version would report.
-
Verify cross-platform consistency. If you use the same profile across different host operating systems (for example, running a Windows profile on both a macOS host and a Linux host), verify that the WebRTC codec capabilities are identical on both hosts. BotBrowser's profile-driven approach should produce the same output regardless of the host, but verification gives you confidence.
-
Monitor for codec-related WebRTC errors. If you encounter WebRTC connectivity issues, check the browser console for codec negotiation errors. BotBrowser handles the gap between profile codecs and locally available codecs gracefully, but certain edge cases with unusual peer configurations may require attention.
Frequently Asked Questions
What is WebRTC codec fingerprinting?
WebRTC codec fingerprinting is a technique where websites query your browser's WebRTC media capabilities to learn which video and audio codecs your system supports. Because codec support varies by operating system and hardware, this information can be used as a tracking signal to infer details about your platform.
How is this different from general media codec fingerprinting?
General media codec fingerprinting uses APIs like canPlayType() and MediaCapabilities. WebRTC codec fingerprinting uses WebRTC-specific APIs: RTCRtpSender.getCapabilities(), RTCRtpReceiver.getCapabilities(), and SDP offers from createOffer(). The WebRTC codec set is not identical to the general media codec set, because WebRTC has its own supported codec list that reflects real-time communication requirements. BotBrowser's profile-driven approach covers both surfaces consistently. For general media codec protection, see the MIME type and codec fingerprinting article.
Can a website query WebRTC codecs without making a call?
Yes. No actual WebRTC connection is needed. RTCRtpSender.getCapabilities('video') is a static method that returns codec information immediately. Similarly, createOffer() generates an SDP document without connecting to any remote peer. Both operations are fast, silent, and require no user interaction or permission.
Does BotBrowser disable any codecs?
No. BotBrowser does not remove or disable codec functionality. Instead, it controls what codec information is reported to JavaScript. The JavaScript-visible codec list matches the loaded profile. Internally, the browser still uses whichever codecs are available on the host system for actual media processing. This means your fingerprint is controlled without sacrificing WebRTC functionality.
What happens if the profile lists a codec my system does not support?
BotBrowser handles this gracefully. The JavaScript-visible APIs report the profile's codec list, maintaining the correct fingerprint. When actual WebRTC media negotiation occurs, the browser internally uses only the codecs that the host system can process. If a profile codec is not locally available, it is excluded from internal processing without affecting the fingerprint presentation. This prevents crashes and ensures that calls still work.
Does this protect audio codecs too?
Yes. BotBrowser's profile-driven codec construction applies to both video and audio capabilities. The audio codec list from getCapabilities('audio') and audio payload types in SDP offers are also derived from the profile data.
How does BotBrowser handle codec ordering?
Codec ordering in capability lists and SDP offers can carry platform-specific information. BotBrowser preserves the exact codec ordering from the profile, which reflects the natural ordering on the target platform. This detail matters because the order in which codecs appear is itself a signal that should match the profile's target.
Does this work with headless mode?
Yes. WebRTC codec capabilities are available in headless mode, and BotBrowser's profile-driven codec construction works identically whether the browser is running headless or with a visible window.
Can I verify the protection without making a real WebRTC call?
Yes. You can verify by calling RTCRtpSender.getCapabilities('video') and createOffer() in a page's JavaScript console or through Playwright/Puppeteer automation. No peer connection or remote server is needed. The code examples in the Configuration and Usage section demonstrate this.
Summary
WebRTC codec enumeration through getCapabilities() and SDP offers exposes media capabilities that differ across operating systems, making the codec list a potential tracking signal. BotBrowser solves this at the engine level by constructing WebRTC codec capabilities entirely from the loaded fingerprint profile. Every API that exposes codec information, from getCapabilities() to createOffer() SDP generation, returns profile-consistent results. The dual-layer separation between the JavaScript-visible codec list and the internally registered decoders ensures that your fingerprint matches the target platform while actual WebRTC functionality continues to work.
Combined with WebRTC IP leak prevention, MIME type and codec protection, cross-platform browser profiles, and comprehensive fingerprint verification, BotBrowser provides thorough control over every WebRTC signal that could reveal your platform identity.
Related Articles
Ready to protect your browser fingerprint?
BotBrowser provides engine-level fingerprint control with real device profiles. Start with a free tier or explore all features.