Request
Two input modes, one endpoint. The mode is selected by the Content-Type header.
QUICKEST
GET with query param
GET /api/parse?url=https://example.com/video.mp4
MODE 1
Parse from URL
POST /api/parse
Content-Type: application/json
{ "url": "https://example.com/video.mp4" }
MODE 2
Parse from raw bytes
POST /api/parse Content-Type: video/mp4 <raw MP4 bytes as the request body>
Response
Example for a 10s clip with one video, one audio and one text track.
{
"success": true,
"source": "url",
"info": {
"duration": 10.026667,
"brands": ["mp42", "isom", "avc1"],
"mime": "video/mp4; codecs=\"avc1.4d400c,mp4a.40.2\"",
"isQuickTime": false,
"overallBitrate": 621714.86,
"timescale": 90000,
"fragmented": false,
"progressive": false,
"tracks": [
{ "id": 1, "type": "video", "codec": "avc1.4d400c",
"width": 320, "height": 240, "bitrate": 51472,
"timescale": 90000, "nb_samples": 250, "language": "und" },
{ "id": 2, "type": "audio", "codec": "mp4a.40.2",
"sampleRate": 44100, "channelCount": 1, "bitrate": 70303,
"timescale": 48000, "nb_samples": 45, "language": "und" }
]
}
}
Schema
successboolean— request succeeded
source"url" | "body"— which input mode was used
info.durationnumber— duration in seconds
info.brandsstring[]— major + compatible brands
info.mimestring— MIME type with codecs parameter
info.isQuickTimeboolean— QuickTime brand detected
info.overallBitratenumber— combined bitrate, bits/s
info.timescalenumber— movie timescale
info.fragmented / progressiveboolean— fMP4 / progressive download
info.tracks[]TrackInfo[]— per-track details
TrackInfo
id · type ("video" | "audio" | "subtitles" | "metadata" | "other") · codec · bitrate · timescale · nb_samples · language · name
video tracks: width, height
audio tracks: sampleRate, channelCount
Errors
400Missing or invalid url; non-http(s) scheme
413Input exceeded the 200MB stream cap
422Not an MP4, or moov atom not found
502Upstream URL unreachable or non-200
500Internal error
Client examples
# quick GET (URL mode only)
curl 'https://your-worker.workers.dev/api/parse?url=https://example.com/video.mp4'
# from a URL
curl -X POST https://your-worker.workers.dev/api/parse \
-H 'Content-Type: application/json' \
-d '{"url": "https://example.com/video.mp4"}'
# from raw bytes
curl -X POST https://your-worker.workers.dev/api/parse \
-H 'Content-Type: video/mp4' \
--data-binary @video.mp4
// quick GET (URL mode only)
const res0 = await fetch('/api/parse?url=' + encodeURIComponent(videoUrl));
// from a URL
const res = await fetch('/api/parse', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url: videoUrl }),
});
const { success, info } = await res.json();
// from a <input type="file"> File/Blob
const res2 = await fetch('/api/parse', {
method: 'POST',
headers: { 'Content-Type': 'video/mp4' },
body: file,
});
import requests
# quick GET (URL mode only)
resp = requests.get(
"https://your-worker.workers.dev/api/parse",
params={"url": "https://example.com/video.mp4"},
)
# from a URL
resp = requests.post(
"https://your-worker.workers.dev/api/parse",
json={"url": "https://example.com/video.mp4"},
)
info = resp.json()["info"]
# from raw bytes
with open("video.mp4", "rb") as f:
resp = requests.post(
"https://your-worker.workers.dev/api/parse",
data=f,
headers={"Content-Type": "video/mp4"},
)