WebM vs MP4 for the web: codecs, browser support and which one to publish

You have a finished clip and three places it might go: a page you build, a platform you upload to, or a person you send it to. WebM and MP4 are the two containers on offer, and the wrong pick fails in the least visible way — it plays perfectly for you and shows a blank rectangle to the one person on an iPhone. This guide sets out what each container may carry, which browsers and chips play which codec, how much VP9 and AV1 really save over H.264, a rule you can apply without looking anything up, and what the converters on this site do to your file on the way.

Two containers, five codecs

A container is the wrapper; a codec is the compression scheme for each stream inside it. MP4 is the ISO Base Media File Format (MPEG-4 Part 14): the file starts with a ftyp box — bytes 66 74 79 70 at offset 4 — and can hold H.264, HEVC, VP9 or AV1 video with AAC, MP3, AC-3 or Opus audio. WebM is a subset of Matroska that Google defined in 2010 and restricted on purpose: only VP8, VP9 or AV1 video and only Vorbis or Opus audio. It begins with the EBML header 1A 45 DF A3, followed within a few bytes by the DocType string webm rather than matroska. Put H.264 into a WebM and every muxer refuses; the restriction is the point.

The point is licensing. H.264 and HEVC are patented. The H.264 pool (Via LA, formerly MPEG LA) has pledged since 2010 never to charge royalties for internet video that is free to the viewer, which is why every browser could ship it; HEVC’s patents sit with at least three pools plus unaffiliated holders, and that uncertainty kept it out of Chrome and Firefox for most of a decade. VP8 (2010), VP9 (2013) and AV1 (2018, from the Alliance for Open Media — Google, Apple, Amazon, Microsoft, Netflix, Mozilla and others) are royalty-free by design. WebM exists so the open web could have video without a licence; MP4 persists because every device made since about 2010 decodes H.264 in silicon.

ContainerVideo codecs allowedAudio codecs allowedFirst bytesLicensing
MP4H.264, HEVC, AV1 (VP9 permitted, rare)AAC, MP3, AC-3, Opus (rare)ftyp at offset 4H.264 royalty-free for free-to-view web video; HEVC under several patent pools
WebMVP8, VP9, AV1 onlyOpus, Vorbis only1A 45 DF A3, DocType webmRoyalty-free throughout

Browser and device support today

The table is what holds as we write this in 2026; check before relying on any single cell, because Apple’s position in particular has moved several times.

CodecChrome and EdgeFirefoxSafari on macOSSafari on iOS
H.264 in MP4YesYesYesYes
HEVC in MP4Only with an OS decoder (Chrome since 107; Edge via the HEVC Video Extensions)Recent versions, via the OS decoder, not everywhereYes, since macOS High SierraYes, since iOS 11
VP8/VP9 in WebMYes, for over a decadeYesSince Safari 14.1 on macOS 11.3 (2021)Later and less complete — test the device
AV1Yes (Chrome since 70)Yes (since 67)Safari 17 and later, only on chips with an AV1 decoder (M3 and newer)Same condition: A17 Pro (iPhone 15 Pro) and newer

Hardware decoding is the hidden variable

Whether a codec plays is a yes-or-no question; whether it plays welldepends on whether the chip decodes it in fixed-function hardware or the CPU does it in software. H.264 has had a hardware decoder in essentially every phone, laptop and TV since about 2010. VP9 decoders arrived with Intel’s 7th-generation chips (2016), most Android SoCs of the same era and Apple’s A14 and M1 (2020). AV1 decoders are newer: Intel 11th generation, NVIDIA RTX 30 and AMD RX 6000 (2020), Snapdragon 8 Gen 2 and Tensor G2 (2022), Apple A17 Pro and M3 (2023). Software AV1 decoding is fine on a laptop and painful on a phone: hot CPU, flat battery, dropped frames. navigator.mediaCapabilities.decodingInfo() answers supported, smooth and powerEfficient for a codec string, and powerEfficient: false means software.

Size and speed: what you save and what it costs

At the same visual quality, VP9 needs roughly 20–40% fewer bits than H.264 and AV1 roughly 30% fewer than VP9 — ranges, because the encoder, its speed setting and the content all move them. The engine behind this site’s converters budgets in the same proportions: at its medium setting it aims for 3 Mbps for 1080p H.264, 1.8 Mbps for VP9 or HEVC, 1.2 Mbps for AV1 and 3.6 Mbps for VP8 — for a 60-second 1080p clip, 22.5 MB, 13.5 MB, 9 MB and 27 MB (bits per second × seconds ÷ 8). VP8 compresses slightly worse than H.264, and it is what most browser screen recorders and the software fallback on this site produce.

The saving is paid at encode time: libvpx-vp9 at its default good deadline runs several times slower than x264 at medium, and the reference AV1 encoder libaom slower by another order of magnitude, which is why practical AV1 encoding uses SVT-AV1 or a 2022-or-later hardware encoder. An encode is paid once; a decode is paid on every view, so for anything with an audience the hardware-decode question outranks the size question.

Where each one belongs

A page you build: one element, two sources

<video controls preload="metadata" poster="clip.jpg" width="1280" height="720">
  <source src="clip.webm" type='video/webm; codecs="vp09.00.10.08, opus"'>
  <source src="clip.mp4"  type='video/mp4; codecs="avc1.640028, mp4a.40.2"'>
</video>

The browser walks the <source> list top to bottom and plays the first one whose type it answers probably or maybe to; it never looks further, so order is preference: the smaller WebM first, the universal MP4 last. Without a type the browser must fetch each candidate and sniff it. The codecs= parameter makes the test precise: labelled only video/webm, an AV1 file is claimed by a browser that decodes VP9 but not AV1 and then fails to play; labelled av01.0.04M.08 it is skipped correctly. The MP4 must also play progressively: its moov box has to precede the media data (ffmpeg’s -movflags +faststart), and the server must answer range requests with 206 Partial Content — Safari sends Range: bytes=0-1 first and will not play from a server that returns 200 with the whole file.

Background loops and transparency

autoplay muted loop playsinline is the attribute set that autoplays everywhere including iOS; drop muted or playsinline and iPhones show the poster and wait. For a silent loop WebM/VP9 is the natural first source, MP4 behind it. Transparency splits by vendor: VP9 in WebM carries an alpha channel that Chrome and Firefox render, while Safari renders HEVC with alpha in a .mov or .mp4 (hvc1) and ignores VP9 alpha. The usual pattern lists the HEVC file first with type='video/mp4; codecs="hvc1"' and the WebM second, because a Chrome without HEVC skips to the WebM; where Chrome decodes HEVC through the OS, test that the transparency survives rather than assume it.

Screen recordings

Chrome’s and Firefox’s MediaRecorder write WebM (VP8 or VP9 with Opus) and, because they stream into a file they cannot seek back into, leave the duration unset — players report Infinity. Safari’s writes MP4. A recording you will keep can stay as it is; one you will send should become MP4 first, which also writes a real duration. The screen-recording guide covers the capture.

Uploads, email and chat

Platforms re-encode whatever you upload into their own renditions, so the container only has to be accepted and carry the best quality you have: MP4 with H.264 and AAC-LC is accepted everywhere and is YouTube’s recommended upload, while WebM is accepted by YouTube and rejected or silently transcoded by several others. Do not shrink to WebM first — the platform’s encode is already the second generation. For a person, MP4 without exception: QuickTime Player and the Finder preview cannot open WebM, Apple Mail shows it as a paperclip, Windows 10 and 11 need the store’s VP9 extension for their built-in players, and WhatsApp, iMessage and Slack build inline previews for MP4. If size is the problem, compress the MP4 rather than switch container — the compress-for-sharing guide has the arithmetic.

How to check what a browser, and a file, can do

// In the console of the browser you care about
document.createElement('video').canPlayType('video/webm; codecs="vp9, opus"');   // "probably", "maybe" or ""
document.createElement('video').canPlayType('video/mp4; codecs="avc1.640028"');
navigator.mediaCapabilities.decodingInfo({
  type: 'file',
  video: { contentType: 'video/webm; codecs="av01.0.04M.08"', width: 1920, height: 1080, bitrate: 2000000, framerate: 30 },
}).then((r) => console.log(r.supported, r.smooth, r.powerEfficient));

An empty string from canPlayType is a definite no; maybe means the container is known but the codec was not stated. The decodingInfo triple is the one that matters on phones: true, true, false plays, but on the CPU. For the file itself, the first bytes name the container and ffprobe the codec:

$ head -c 12 clip.webm | xxd
00000000: 1a45 dfa3 a342 8681 0142 f781            .E...B...B..
$ head -c 12 clip.mp4 | xxd
00000000: 0000 0020 6674 7970 6973 6f6d            ... ftypisom
$ ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,profile,pix_fmt,width,height -of default=nw=1 clip.mp4
codec_name=h264
profile=High
pix_fmt=yuv420p
width=1920
height=1080

The pix_fmt line is the one people miss — only yuv420p plays everywhere (more under Common mistakes) — and dropping -select_streams v:0 shows the audio line, where codec_name=opus inside an .mp4 is the trap described next.

Converting on this site

The WebM converter, the MP4 converter and the video compressorare one engine with a different target preselected, and the file never leaves the browser tab. When you drop a file the page probes it: if the browser’s WebCodecs decoder can handle the primary video track and the container is MP4, MOV, MKV, WebM, 3GP or MPEG-TS, the hardware route runs; otherwise, and always for AVI, FLV and WMV, an ffmpeg.wasm build takes over. The dialog offers Convert to (on the compressor), Resolution (Keep original, 360p, 480p, 720p, 1080p), Target file size in MB, Mute and Compress; output is name_output.webm or name_output.mp4, and several files arrive as converted-videos.zip.

To WebM

On the hardware route a track the container accepts is copied unchanged, so a VP9 or AV1 file with Opus becomes WebM in seconds. H.264 or HEVC video must be re-encoded, and the engine takes the first codec the browser’s encoder accepts in the order VP9, AV1, VP8 — on current Chrome and Edge, VP9. AAC audio becomes Opus (Vorbis if Opus cannot be encoded); if neither can, the audio track is dropped and the WebM is silent. Alpha is discarded on both routes. Tick Compress and the VP9 target is about 1.8 Mbps at 1080p (1.2 Mbps for AV1); a source taller than 1080 lines converts at full size and the dialog says High-resolution source — converts at original size using your device's hardware encoder. On the ffmpeg route the encode is VP8, not VP9: -c:v libvpx -deadline realtime -cpu-used 5 -crf 10 -b:v 2M -c:a libopus (-crf 34 -b:v 1M with Compress), capped at 1080p — High-resolution source — output is capped at 1080p for in-browser conversion on this device. Pick 720p for a smaller, faster file. — and unable to load files above about 2 GB.

To MP4

The same logic in reverse, with one trap. The MP4 the engine writes accepts H.264, HEVC, VP9, AV1 and even VP8, plus AAC, MP3, Opus and AC-3, so a Chrome screen recording (VP8 with Opus) converted with no options is copied through — a valid MP4 with vp08 and Opus sample entries that Chrome and Firefox play and Safari, iPhones and QuickTime do not. Ticking Compress forces the video through the encoder, and H.264 is first in the MP4 list, so it comes out as H.264 at about 3 Mbps for 1080p; the audio is still copied as Opus. Only a Target file size sends the audio through an encoder too (128 kbps, AAC where the browser can encode it). So for an MP4 meant for other people, set a target size and confirm codec_name=h264 and codec_name=aac with ffprobe. The ffmpeg route (AVI, WMV, FLV, or a codec the browser cannot decode) always produces -c:v libx264 -preset superfast with AAC audio — the universally playable pair, at the cost of the 1080p cap. Any failure on either route ends with Conversion failed. The file may be unsupported, corrupted, or too large to process in this browser.

The rule

  1. Publish MP4 as the baseline for everything: H.264 High or Main profile, yuv420p, AAC-LC, moov first. It is the only file that plays in every cell of the table above.
  2. Add WebM (VP9 with Opus) as the first source only where you control the playerand have measured the saving on your own clip. A 40% cut on a 300 KB loop is nothing; on a 40 MB hero video it is the page’s largest asset.
  3. Reach for AV1 only behind a player that can fall back per device, or for an audience you know decodes it in hardware.
  4. Never send WebM to a person, and never upload a WebM you shrank. Compress the MP4 instead.
  5. Keep the original and make every derivative from it, not from a previous derivative.

Common mistakes

  • Relying on WebM for iOS users. Safari 14.1 on a Mac is not every iPhone in the wild, and in-app browsers use whatever WebKit the phone shipped with. Ship the MP4 source; the cost is one extra file.
  • Listing the MP4 first, or omitting type. With MP4 first, Chrome takes the MP4 and the WebM is never requested: two files uploaded, nothing saved.
  • The wrong flavour of H.264. x264 keeps the pixel format of its input, so an RGB screen capture comes out 4:4:4 and does not play in browsers; 10-bit and Level 5.1 (4K) files fail on older phones and TVs. Use -profile:v high -level 4.1 -pix_fmt yuv420p for anything the public must play.
  • Audio that does not match the container.Opus in MP4 was standardised in 2018, but Safari’s support arrived late and partially — use AAC. AAC cannot go into WebM at all. The MP4 converter above copies Opus through unless you set a target size, so check with ffprobe, not the extension.
  • A server that does not know WebM. IIS returns 404.3 for .webm until <mimeMap fileExtension=".webm" mimeType="video/webm" /> is added to web.config; Nginx and Apache ship both types.
  • Expecting transparency to survive a conversion. Both routes on this site drop the alpha channel; export an overlay with alpha from the editor that made it and keep that master.

Do this

  • Make an H.264/AAC MP4 (yuv420p, moov first) of every clip you publish; it is the file you upload and the file you send.
  • On your own pages, add a VP9/Opus WebM as the first <source> with a full type attribute, and the MP4 second.
  • Before serving AV1, run decodingInfo() on the devices you care about and look at powerEfficient, not just supported.
  • When converting a screen recording to MP4 for other people, set a target size so both video and audio are re-encoded, then verify with ffprobe.
  • Keep the original; make every WebM, MP4 or compressed copy from it, never from another copy.

Frequently asked questions

Is WebM better than MP4?

Smaller, usually: VP9 in WebM needs roughly 20–40% fewer bits than H.264 in MP4 for the same picture, and AV1 fewer still. MP4 with H.264 plays on more devices and decodes in hardware on nearly all of them. On a page you control, list the WebM first with an MP4 fallback; for anything you upload or send to a person, use MP4.

Does Safari play WebM files?

Safari on the Mac has played WebM with VP8 or VP9 since Safari 14.1 on macOS 11.3 (2021). Support on iPhone and iPad came later and is less complete, and QuickTime Player and the Finder preview still do not open WebM at all, so treat Apple users as an MP4 audience unless you have tested the exact device.

Can I send a WebM by email or WhatsApp?

You can attach it, but the recipient often cannot play it: Apple Mail, QuickTime and older Windows players have no WebM decoder, and chat apps build their inline previews for MP4. Convert to MP4 with H.264 video and AAC audio before sending.

Should I upload MP4 or WebM to YouTube?

Either uploads, but send the best-quality file you have. YouTube re-encodes everything into its own H.264, VP9 and AV1 renditions, so a WebM you shrank to save upload time only gives it a worse source. Its recommended upload is MP4 with H.264 video and AAC-LC audio.

How do I convert WebM to MP4 without uploading it anywhere?

Drop the file on the MP4 converter on this site and set a target file size, so the video is re-encoded to H.264 and the audio to AAC instead of being copied through as VP8 or VP9 with Opus. The work happens in your browser; nothing is sent to a server.

Tools used in this guide

Every one of these runs in your browser — the files you work on never leave your device.

More video guides