Video container and codec compatibility checker
Video playback depends on two separate choices: the container that organizes the media and the codec that compresses the picture.
Run — free
A familiar file extension does not guarantee that the video stream inside it will play everywhere. This compatibility checker evaluates MP4, MOV, MKV, WebM, and AVI paired with H.264, H.265, VP9, or AV1. It gives a conservative support level, explains the main interoperability concern, and recommends when to provide a widely playable fallback.
Understand what the compatibility result means
The checker uses three support levels rather than pretending playback is a simple technical yes or no. Broad means the pairing is a dependable delivery choice across current major web browsers and modern iOS and Android environments. Limited means the combination has real support, but important gaps remain because of browser family, operating-system version, device hardware, or the way the codec is normally packaged. Poor means the pairing is unconventional for browser delivery or cannot be relied upon in native mobile players. The separate broadly supported boolean makes automated decisions straightforward, while the explanation preserves the reason behind the classification. This is a format-level assessment, not a promise about every encoded file. Codec profile, level, resolution, bit depth, frame rate, audio codec, encryption, and damaged metadata can still prevent playback even when the container and video codec are a broadly supported pair. Treat the result as an early architecture check before encoding and device testing, not as a substitute for testing representative output files on the platforms your audience actually uses.
Choose a container and codec together
A codec describes how video frames are compressed; a container describes how video, audio, timing, subtitles, and metadata are packaged. Those layers are related but not interchangeable. H.264 inside MP4 is broadly portable because both the compression format and its packaging have mature browser and mobile implementations. The same H.264 stream inside AVI or MKV may play in a desktop media application yet fail as an embedded web video or in a mobile system player. Likewise, VP9 is naturally associated with WebM for browser delivery, while putting VP9 into MOV creates an unusual combination with little dependable interoperability. Newer codecs can reduce bandwidth, but efficiency alone does not make a delivery format universal. H.265 has particularly strong support in Apple environments, while support elsewhere depends more heavily on browser, operating system, licensing choices, and hardware. AV1 adoption continues to expand, but older phones and devices without suitable decoding may still be important to a real audience. Select the pair as one delivery decision, then verify audio and encoding settings separately.
Plan fallbacks and production testing
For the widest practical reach, use MP4 with H.264 as the baseline asset. When bandwidth or quality goals justify VP9, AV1, or H.265, offer the newer encoding as an additional source instead of assuming one advanced file will serve every visitor. A web player can list multiple sources and allow the browser to choose a format it understands; applications can make a similar decision from platform and decoder capabilities. Keep the fallback independently encoded and verify that the server sends the correct media type, supports byte-range requests, and permits the required cross-origin access. Test real files because a matrix cannot see profile, level, pixel format, color information, audio codec, or malformed metadata. Include representative older and newer iPhones, Android devices, and the browser families your analytics show, then test both streaming startup and seeking. Recheck compatibility when you change the encoding ladder or minimum supported OS versions. The checker is most useful in CI, content intake, or publishing workflows as a fast warning that prevents an obviously fragile pairing from becoming the only distributed asset.
What you can do with it
Choose a web delivery format
Compare a proposed container and codec before configuring an encoding pipeline or HTML video source.
Validate uploaded media
Warn publishers when an uploaded pairing is unlikely to play consistently in browsers and native mobile players.
Enforce a fallback policy
Use the broad-support boolean in CI to require an MP4/H.264 fallback alongside newer efficient formats.
FAQ
Does a broad result guarantee playback everywhere?
No. It indicates strong format-level coverage, but encoding profile, level, bit depth, audio, encryption, metadata, and individual browser versions also affect playback.
Why are container and codec checked separately?
The codec compresses the video while the container packages that stream with timing, audio, and metadata. Platforms may support a codec in one container but not another.
What is the safest fallback?
Among the available choices, MP4 with H.264 is the most dependable general-purpose fallback for browsers, iOS, and Android.
Does the checker inspect my video file?
No. It evaluates the container and codec names you provide. Use a metadata inspection tool to identify streams in an existing file.
Why can a limited combination still work on my phone?
Limited means meaningful support exists but is not consistent enough across browser families, operating-system versions, and devices to count as broad.
How much does a request cost?
Each API request costs $0.002. The browser implementation uses the same deterministic compatibility logic.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/video/container-compatibility \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"container":"mp4","codec":"h264"}'const res = await fetch("https://api.kit.forhosting.com/video/container-compatibility", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"container": "mp4",
"codec": "h264"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/video/container-compatibility",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"container": "mp4",
"codec": "h264"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/video/container-compatibility", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"container":"mp4","codec":"h264"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"container":"mp4","codec":"h264"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/video/container-compatibility", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"container": "mp4",
"codec": "h264"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "video.container_compatibility",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 500 |
max_minutes | 60 |
max_megapixels | 3.9 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |