World’s largest virtual agentic engineering & quality conference
MediaRecorder works in Chrome 49+, Edge 79+, Firefox 29+, Opera 36+, Safari 14.1+ macOS, and Safari 14.5+ iOS. Safari records audio/webm from 18.4. Codecs, fallbacks, quirks.

Prince Dewani
Author
Last Updated on: May 1, 2026
MediaRecorder is a W3C JavaScript API that records audio and video from a MediaStream into a Blob. It supports Chrome 49+, Edge 79+, Firefox 29+, Opera 36+, Samsung Internet 5+, Safari 14.1+ on macOS, and Safari 14.5+ on iOS; Internet Explorer and the legacy Android Browser do not support it.
The question most developers arrive with is whether Safari can record audio/webm. As of Safari 18.4, released March 2025, it can: WebKit added WebM recording with Opus audio and VP8 or VP9 video. On Safari 14.1 through 18.3 it cannot, and you fall back to audio/mp4 with AAC. Because the answer depends on the version in front of you, ask the browser rather than the user agent:
// Does this browser record WebM audio, or do we need MP4?
const webm = MediaRecorder.isTypeSupported('audio/webm;codecs=opus');
const mp4 = MediaRecorder.isTypeSupported('audio/mp4');
// Chrome / Firefox / Edge -> webm true
// Safari 18.4+ / iOS 18.4+ -> webm true, mp4 true
// Safari 14.1 - 18.3 -> webm false, mp4 true
const mimeType = webm ? 'audio/webm;codecs=opus' : 'audio/mp4';This guide covers what MediaRecorder is, the browsers that support it, the codecs it accepts, how to record audio and video in Safari and on iOS, the truth about WebM playback and transcoding, how to check support, how to enable it in older Safari, and the known issues.
MediaRecorder is a W3C JavaScript interface in the MediaStream Recording API that records a MediaStream into a Blob of encoded audio or video. The MediaStream usually comes from getUserMedia, getDisplayMedia, or a Web Audio graph. It exposes start, stop, pause, resume, and dataavailable events to the page.
MediaRecorder works in every modern desktop and mobile browser. Chrome, Firefox, Edge, Opera, and Samsung Internet support it on Windows, macOS, Linux, ChromeOS, and Android, while Safari supports it from Safari 14.1 on macOS and Safari 14.5 on iOS.
Chrome supports MediaRecorder by default from Chrome 49 on Windows, macOS, Linux, ChromeOS, and Android. Chrome 47 to 48 had MediaRecorder disabled by default behind the experimental web platform features flag and only recorded video. Chrome 4 to 46 did not support the API.
Edge supports MediaRecorder by default from Edge 79 on Windows, macOS, Linux, and Android. Edge 79 was the first Chromium-based release, so it inherits the same recorder behavior as Chrome. The legacy EdgeHTML versions Edge 12 to 78 never added MediaRecorder.
Firefox supports MediaRecorder by default from Firefox 29 on Windows, macOS, Linux, and Android. Audio and video recording both work from version 29, and later releases added codec choices and bitrate hints. Firefox 2 to 28 did not support the API.
Safari supports MediaRecorder by default from Safari 14.1 on macOS Big Sur and from Safari 14.5 on iPhone and iPad. Safari 12.1 to 14 on macOS and Safari 12 to 14.4 on iOS shipped MediaRecorder behind an Experimental Features toggle. Safari 11 and earlier on macOS, and Safari 11.4 and earlier on iOS, did not support it.
Having the API is only half the answer in Safari, because which container it will write changed partway through. From Safari 14.1 to 18.3, Safari's MediaRecorder was strictly limited to MP4 with H.264 video and AAC audio. Asking for WebM returned false and there was no way around it. Safari 18.4 lifted that limit, adding WebM with Opus, VP8, and VP9, plus Ogg, fragmented MP4, ALAC and PCM lossless audio, and HEVC and AV1 video. Both facts matter: the version tells you whether the API exists, and 18.4 tells you what it will accept.
Opera supports MediaRecorder by default from Opera 36 on Windows, macOS, and Linux, and from Opera Mobile 80 on Android. Opera 34 to 35 had MediaRecorder disabled by default, and Opera 9 to 33 did not support it. Modern Chromium-based Opera shares Chrome's behavior.
Samsung Internet supports MediaRecorder by default from version 5 on Galaxy phones and tablets. It is built on Chromium, so it inherits the same audio and video MIME types Chrome supports. Samsung Internet 4 did not support the API.
The legacy stock Android Browser does not support MediaRecorder in any version. On modern Android phones, use Chrome for Android 49+, Firefox for Android 29+, or Samsung Internet 5+ for MediaRecorder support. The stock browser only ships on Android 4.4 KitKat and earlier devices.
Internet Explorer does not support MediaRecorder in any version. Microsoft never added the MediaStream Recording API to IE 5.5 through IE 11. Microsoft has retired Internet Explorer in favor of Edge, so any new build should target Edge or another Chromium-based browser.
Note: MediaRecorder breaks across older Safari, iOS, and the stock Android Browser. Test it on real browsers and OS with TestMu AI. Try TestMu AI free!
MediaRecorder supports a different list of MIME types in each browser, so call MediaRecorder.isTypeSupported() before recording. Chromium browsers default to audio/webm with Opus and video/webm with VP8 or VP9. Safari wrote only audio/mp4 and video/mp4 with AAC and H.264 until Safari 18.4, which added WebM, Ogg, fragmented MP4, and lossless audio.
Safari 18.4, released in March 2025, is the dividing line for most of this table. Before it, Safari recorded MP4 and nothing else; after it, Safari records WebM, Ogg, fragmented MP4, and lossless audio. If you are reading advice written before that date, including advice that says Safari cannot record WebM, check the date on it.
Can you record audio/webm in Safari? Yes, from Safari 18.4. WebKit shipped WebM recording in Safari 18.4 on macOS Sequoia 15.4, iOS 18.4, and iPadOS 18.4, all released in March 2025, using the Opus audio codec with VP8 or VP9 for video. On those versions, MediaRecorder.isTypeSupported('audio/webm;codecs=opus') returns true.
On Safari 14.1 through 18.3 it returns false. Those versions record MP4 only, with AAC for audio and H.264 for video. So the answer to "can I use MediaRecorder audio/webm in Safari" is genuinely "it depends on the version", which is exactly the situation feature detection exists for. Do not branch on the user agent string here; a version check you write today is wrong the moment Apple ships an update.
Ask the browser instead. Walk a list of candidates in preference order and take the first one it accepts:
// Pick the best audio MIME type this browser will actually record.
// Order matters: first match wins.
function pickAudioMimeType() {
const candidates = [
'audio/webm;codecs=opus', // Chrome, Firefox, Edge, Safari 18.4+
'audio/mp4;codecs=mp4a.40.2', // Safari 14.1 - 18.3 (AAC)
'audio/mp4', // Safari, looser form
'audio/ogg;codecs=opus', // Firefox
];
return candidates.find((type) => MediaRecorder.isTypeSupported(type)) ?? '';
}
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mimeType = pickAudioMimeType();
// If nothing matched, omit mimeType entirely and let the browser choose.
// Passing { mimeType: '' } throws.
const recorder = new MediaRecorder(stream, mimeType ? { mimeType } : undefined);
const chunks = [];
recorder.ondataavailable = (e) => e.data.size && chunks.push(e.data);
recorder.onstop = () => {
// Read the type back: the browser may have normalised what you asked for.
const blob = new Blob(chunks, { type: recorder.mimeType });
upload(blob, recorder.mimeType);
};
try {
recorder.start();
} catch (err) {
// isTypeSupported() has historically returned true on iOS for types
// that then failed at start(). Never skip this guard.
console.error('start() failed for', mimeType, err);
}Three details in that snippet are worth calling out, because each one is a bug someone has shipped.
Video has more moving parts than audio, because a video MIME type names two codecs rather than one, and iOS is the platform where guessing wrong costs you the most. The safest target on any iOS version that supports MediaRecorder at all is H.264 Baseline with AAC:
// H.264 Baseline + AAC is the safest target on any MediaRecorder-capable iOS.
function pickVideoMimeType() {
const candidates = [
'video/mp4;codecs=avc1.42E01E,mp4a.40.2', // Safari / iOS 14.5+
'video/mp4',
'video/webm;codecs=vp9,opus', // Chromium, Firefox, Safari 18.4+
'video/webm;codecs=vp8,opus',
];
return candidates.find((type) => MediaRecorder.isTypeSupported(type)) ?? '';
}
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: { facingMode: 'user' },
});
const mimeType = pickVideoMimeType();
const recorder = new MediaRecorder(stream, mimeType ? { mimeType } : undefined);That codec string is not arbitrary, and it is worth being able to read rather than copy. In avc1.42E01E, the avc1 means H.264, the 42 means Baseline profile, the E0 carries the constraint flags, and the 1E is hexadecimal for 30, meaning Level 3.0. In mp4a.40.2, the 40 means MPEG-4 audio and the 2 means AAC-LC. Baseline at Level 3.0 is the conservative choice precisely because every iOS device that can record at all can encode it.
From Safari 18.4 the range widens considerably. WebKit's own example pairs H.264 with Opus inside MP4:
// Safari 18.4+ : H.264 video with Opus audio, inside MP4.
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: true,
});
const recorder = new MediaRecorder(stream, {
mimeType: 'video/mp4; codecs=avc1.42000a,opus',
});Safari 18.4 also records HEVC, and AV1 on devices that have hardware AV1 support, which is a meaningful qualifier: AV1 is a device capability, not a Safari capability, so isTypeSupported() will answer differently on two phones running identical software. That is another reason to detect rather than assume.
Two constraints apply to iOS regardless of codec. getUserMedia only works in a secure context, so the page must be on HTTPS or localhost, and capture must begin from a user gesture such as a tap rather than on page load.
There is a widely repeated claim that Safari cannot play WebM and that you must transcode every WebM recording to MP4 on the server before an iPhone can open it. It was true once. It has not been true for years, and acting on it now means paying for a transcoding pipeline you do not need.
Safari has played WebM since Safari 14.1 on macOS Big Sur 11.3, released April 2021, and since iOS 15, released September 2021. A WebM file recorded in Chrome plays natively in current Safari on both platforms. Note that recording and playback are separate capabilities with separate histories: Safari could play WebM for almost four years before it could record it.
The real problem was narrower and stranger than the myth, and it is the reason the myth stuck. WebM containing Opus audio, which is exactly what Chrome's MediaRecorder produces by default, behaved inconsistently on iOS. On macOS it worked. On iOS, Web Audio's decodeAudioData() could decode the file, but canPlayType() reported no support and the audio element refused to play it. Since canPlayType() is the standard way to feature-detect playback, applications correctly concluded the format was unsupported and fell back to transcoding. That was tracked as WebKit bug 238546, filed against Safari 15.4 in March 2022, and reports on the bug indicate it was resolved around Safari 17.4 in March 2024.
So the practical question is not whether Safari plays WebM. It is which Safari versions you still support:
When you do need it, the operation is usually a remux rather than a full transcode, and the distinction matters for your bill. Remuxing rewrites the container while leaving the encoded streams untouched, which is fast and lossless. Transcoding decodes and re-encodes, which is slow, lossy, and CPU-expensive. Going from WebM with VP8 or VP9 to MP4 requires a real transcode, because MP4 will not carry VP8; going from a WebM that already holds H.264 to MP4 is a remux. FFmpeg does both, and -c copy is the flag that tells it not to re-encode.
The cheapest strategy of all is to skip the server work entirely: feature-detect at record time, capture MP4 directly on the clients that need MP4, and leave everyone else on WebM. That is what the fallback snippet earlier in this guide does.
Test MediaRecorder support in two steps. First, check that the MediaRecorder constructor exists in window. Second, call MediaRecorder.isTypeSupported() with the MIME type you plan to record. Both calls return synchronously, so they fit inside a feature-detect block before getUserMedia.
The isTypeSupported() call returns a boolean. A true result means the browser will accept the MIME type, but it does not promise the encoder can run at the requested bitrate on the current device. Always wrap MediaRecorder.start() in a try/catch and listen for the error event in case the encoder rejects the stream at runtime.
Paste this snippet into the browser DevTools console to confirm the constructor and the four most common MIME types:
// Run in the DevTools console of any browser to test MediaRecorder support.
const hasMediaRecorder = "MediaRecorder" in window;
console.log("MediaRecorder constructor:", hasMediaRecorder ? "yes" : "no");
if (hasMediaRecorder) {
const mimeChecks = [
"audio/webm;codecs=opus",
"audio/mp4;codecs=mp4a.40.2",
"video/webm;codecs=vp9,opus",
"video/mp4;codecs=avc1.42E01E,mp4a.40.2"
];
for (const mime of mimeChecks) {
const ok = MediaRecorder.isTypeSupported(mime);
console.log(mime, "->", ok ? "yes" : "no");
}
}If every MIME prints "no", the browser cannot record at all and your page should fall back to a server-side recorder or a WebRTC pipe to the backend.
Safari supports MediaRecorder by default from Safari 14.1 on macOS and Safari 14.5 on iOS. On older Safari 12.1 to 14 on macOS and Safari 12 to 14.4 on iOS, the API ships but is disabled, so flip the experimental flag before any page can use it.
On iPhone or iPad, open Settings, Safari, Advanced, Experimental Features, toggle MediaRecorder on, and reload Safari. The flag is sticky, so you only have to do it once per device.
MediaRecorder has the broadest reach of any web recording API, but a few real edge cases still break in production. The biggest hits are codec interop, iPhone Safari quirks, and the legacy Android Browser gap.
The most surprising failure has always been on iPhone Safari, where isTypeSupported() and the encoder could disagree: the check returned true, start() threw NotSupportedError, and the page silently recorded nothing. Safari 18.4 removed the most common trigger for this by making WebM genuinely recordable, so a true answer for audio/webm now means what it says. The habit is still worth keeping. isTypeSupported() reports whether a MIME type is recognised, not whether the encoder can run at your requested bitrate on this particular device, and AV1 recording is a hardware capability that varies between phones on identical software. Test the actual start() call, not just isTypeSupported().
All MediaRecorder version numbers and platform notes in this guide come from these primary sources:
Author
Prince Dewani is a Community Contributor at TestMu AI specializing in AI agents, software testing, QA, and SEO. He is certified in Selenium, Cypress, Playwright, Appium, Automation Testing, and KaneAI, and presented academic research on AI agents at PBCON-01. At TestMu AI, he has also carried out extensive cross-browser research on the support of modern web technologies such as WebGPU, WebAssembly, WebXR, WebGL2 and other web technologies, validating their compatibility and feature parity across major browsers and rendering engines through rigorous hands-on testing. Prince has hands-on experience building AI agent workflows using Anthropic Claude, Google Antigravity, n8n, LangChain, and other agentic frameworks, and works regularly with MCP and A2A protocols. He shares his work with 5,500+ QA engineers, developers, DevOps experts, tech leaders, and AI agent practitioners on LinkedIn.
Did you find this page helpful?
More Related Blogs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance