World’s largest virtual agentic engineering & quality conference

WHENAUG 19-21
WHEREVirtual · Global
Register Now
Testing

MediaRecorder: Browser Support, Codecs, Limitations

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.

Author

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.

What is MediaRecorder?

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.

Which browsers does MediaRecorder support?

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.

Loading browser compatibility data...

MediaRecorder compatibility in Chrome

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.

MediaRecorder compatibility in Edge

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.

MediaRecorder compatibility in Firefox

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.

MediaRecorder compatibility in Safari

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.

MediaRecorder compatibility in Opera

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.

MediaRecorder compatibility in Samsung Internet

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.

MediaRecorder compatibility in Android Browser

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.

MediaRecorder compatibility in Internet Explorer

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

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!

What codecs and MIME types does MediaRecorder support?

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.

  • WebM with VP8 or VP9: Chrome 49+, Edge 79+, Firefox 29+, Opera 36+, and Samsung Internet 5+ all write audio/webm and video/webm. Safari joined them in Safari 18.4, which added WebM recording with Opus audio and VP8 or VP9 video.
  • WebM with H.264: Chrome 52+ accepts video/webm;codecs=h264 on platforms that ship a hardware H.264 encoder. Firefox returns false from isTypeSupported() for that MIME.
  • MP4 with H.264 and AAC: Safari 14.1+ on macOS and Safari 14.5+ on iOS write video/mp4 and audio/mp4. Safari 18.4 extended this to fragmented MP4 (ISOBMFF), which pairs directly with Media Source Extensions, and added HEVC and AV1 video on devices with hardware support. Chrome writes mp4 only when the platform offers an OS encoder, so test with isTypeSupported() first.
  • Audio/webm with Opus: every WebM-supporting browser accepts audio/webm;codecs=opus, including Safari from 18.4.
  • Audio/ogg with Opus: Firefox 29+ writes audio/ogg;codecs=opus. Safari added Ogg container support for Opus and Vorbis in Safari 18.4 on macOS Sequoia 15.4, iOS 18.4, iPadOS 18.4, and visionOS 2.4. Chromium browsers do not.
  • ALAC and PCM: Safari 18.4 ships lossless audio recording in ALAC and PCM. Before that these were Technology Preview only. Firefox does not write them.

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.

How to record audio in Safari: WebM vs MP4 fallbacks

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.

  • Omit mimeType rather than passing an empty string. If nothing matches, new MediaRecorder(stream, { mimeType: '' }) throws. Passing no options at all lets the browser pick its own default, which is a better outcome than a crash.
  • Read back recorder.mimeType, do not assume it. The browser can normalise what you asked for, and the value it reports is the one that describes the Blob you are about to upload. Your server needs that string to store the file with the right extension and content type.
  • Still wrap start() in a try/catch. isTypeSupported() returning true has historically not guaranteed that start() succeeds on iOS. The cost of the guard is three lines; the cost of skipping it is a page that silently records nothing.

Recording video on iOS Safari: supported MIME types and codecs

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.

WebM playback and transcoding in Safari

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:

  • Current Safari and iOS: no transcoding needed. Serve the WebM as recorded.
  • iOS roughly 15.4 to 17.3: WebM with Opus audio will not play through the audio or video element even though the container is supported. This is the band where remuxing genuinely earns its cost.
  • macOS Safari below 14.1, or iOS below 15: no WebM playback at all. Transcode, or serve MP4 to those clients.

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.

How do you check if a browser supports MediaRecorder?

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.

Run tests up to 70% faster on the TestMu AI cloud grid

How to enable MediaRecorder in Safari?

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.

  • Show the Develop menu: Open Safari, Settings, Advanced, and tick "Show features for web developers" so the Develop menu appears in the menu bar.
  • Open Feature Flags: Click Develop, Feature Flags (or Develop, Experimental Features on Safari 14 and earlier) to load the flag panel.
  • Toggle MediaRecorder: Search for MediaRecorder in the flag list and switch it on.
  • Reload the page: Close and reopen Safari, then reload your page so the flag takes effect.
  • Confirm support: Open the JavaScript console and run typeof MediaRecorder; if the result is "function", the flag is live.

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.

What are the known issues with MediaRecorder?

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.

  • Older Safari kept it behind a flag: Safari 12.1 to 14 on macOS and Safari 12 to 14.4 on iOS shipped MediaRecorder behind Experimental Features. Sites that target visitors on macOS Big Sur 11.2 or iOS 14.4 still need a server-side recorder fallback.
  • Recording defaults still differ: Chrome and Firefox write audio/webm with Opus, while Safari defaults to audio/mp4 with AAC even on 18.4+, which can record WebM if you ask for it. Playback is no longer the problem it once was: Safari has played WebM since 14.1 on macOS and iOS 15, so a Chrome-recorded WebM opens in current Safari without re-muxing. Only iOS between roughly 15.4 and 17.3 refuses WebM with Opus audio through the media elements.
  • IE and Android Browser never supported it: IE 5.5 through 11 and the stock Android Browser do not include MediaRecorder. Use Edge, Chrome, or Firefox on those platforms.
  • Firefox does not write video/webm with H.264: Chrome 52+ accepts video/webm;codecs=h264 on platforms with hardware H.264, but Firefox returns false from isTypeSupported() for that MIME.
  • timeslice quirk in Firefox: Firefox's start(timeslice) does not strictly chunk data on the timeslice boundary, so Blobs from short timeslices can be larger than the requested window.
  • Constraints reset audio in older Chrome: Calling track.applyConstraints() on a recording track silently resets the encoder in Chrome 90 and earlier. Pause MediaRecorder before applying new constraints, then resume.

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().

Test your website on the TestMu AI real device cloud

Citations

All MediaRecorder version numbers and platform notes in this guide come from these primary sources:

Author

...

Prince Dewani

Blogs: 15

  • Linkedin

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.

Open in ChatGPT Icon

Open in ChatGPT

Open in Claude Icon

Open in Claude

Open in Perplexity Icon

Open in Perplexity

Open in Grok Icon

Open in Grok

Open in Gemini AI Icon

Open in Gemini AI

Copied to Clipboard!
...

3000+ Browsers. One Platform.

See exactly how your site performs everywhere.

Try it free
...

Write Tests in Plain English with KaneAI

Create, debug, and evolve tests using natural language.

Try for free
...
TestMu Conf 2026

World's largest virtual agentic engineering & quality conference

...

AUG 19-21, 2026

REGISTER NOW

Frequently asked questions

Did you find this page helpful?

More Related Blogs

TestMu AI forEnterprise

Get access to solutions built on Enterprise
grade security, privacy, & compliance

  • Advanced access controls
  • Advanced data retention rules
  • Advanced Local Testing
  • Premium Support options
  • Early access to beta features
  • Private Slack Channel
  • Unlimited Manual Accessibility DevTools Tests