How to Download MP4 Videos
File Extensions: .mp4, .m4v, .m4a MIME Types: video/mp4, audio/mp4 Container: Multimedia container Codecs: H.264, H.265, AAC, and many others
File Extensions: .mp4, .m4v, .m4a
MIME Types: video/mp4, audio/mp4
Container: Multimedia container
Codecs: H.264, H.265, AAC, and many others
Overview
MP4 is a digital multimedia container format most commonly used to store video and audio, but can also store other data such as subtitles and still images. It's based on Apple's QuickTime File Format (.mov) and is defined by the ISO/IEC 14496-14 standard.
Structure
MP4 files use a hierarchical structure of "atoms" or "boxes":
ftyp (File Type Box)
mdat (Media Data Box)
moov (Movie Box)
├─ mvhd (Movie Header)
├─ trak (Track Box)
│ ├─ tkhd (Track Header)
│ ├─ mdia (Media Box)
│ │ ├─ mdhd (Media Header)
│ │ ├─ hdlr (Handler Reference)
│ │ └─ minf (Media Information)
│ └─ ...
└─ ...
Detection Methods
1. File Extension and MIME Type
// Check file extension
function isMP4(filename) {
return /\.(mp4|m4v|m4a)$/i.test(filename);
}
// Check MIME type
function isMP4MimeType(mimeType) {
return /^(video|audio)\/mp4$/i.test(mimeType);
}
2. Network Traffic Analysis
// Browser Network monitoring
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
if (entry.name.includes('.mp4')) {
console.log('MP4 detected:', entry.name);
}
});
});
observer.observe({ entryTypes: ['resource'] });
3. HTML Video Element Detection
// Find all video elements with MP4 sources
function findMP4Videos() {
const videos = [];
document.querySelectorAll('video').forEach(video => {
// Check main src
if (video.src && isMP4(video.src)) {
videos.push({ element: video, src: video.src });
}
// Check source elements
video.querySelectorAll('source').forEach(source => {
if (source.src && isMP4(source.src)) {
videos.push({ element: video, src: source.src, type: source.type });
}
});
});
return videos;
}
4. Binary File Header Detection
// Detect MP4 by file header (magic bytes)
async function detectMP4Header(arrayBuffer) {
const view = new DataView(arrayBuffer);
// Check for ftyp box at offset 4
const ftyp = String.fromCharCode(
view.getUint8(4), view.getUint8(5), view.getUint8(6), view.getUint8(7)
);
if (ftyp === 'ftyp') {
// Check major brand
const majorBrand = String.fromCharCode(
view.getUint8(8), view.getUint8(9), view.getUint8(10), view.getUint8(11)
);
// Common MP4 brands
const mp4Brands = ['isom', 'mp41', 'mp42', 'dash', 'msdh', 'msix', 'avc1'];
return mp4Brands.includes(majorBrand);
}
return false;
}
// Usage with fetch
async function checkIfMP4(url) {
const response = await fetch(url, {
method: 'HEAD',
headers: { 'Range': 'bytes=0-31' }
});
const buffer = await response.arrayBuffer();
return detectMP4Header(buffer);
}
Download Methods
1. Direct HTTP Download
# Simple wget download
wget "https://example.com/video.mp4"
# With custom headers
wget --header="Referer: https://example.com/" \
--header="User-Agent: Mozilla/5.0..." \
"https://example.com/video.mp4"
# Resume partial download
wget -c "https://example.com/video.mp4"
2. curl Download
# Basic download
curl -o video.mp4 "https://example.com/video.mp4"
# With headers
curl -H "Referer: https://example.com/" \
-H "User-Agent: Mozilla/5.0..." \
-o video.mp4 \
"https://example.com/video.mp4"
# With progress bar
curl --progress-bar -o video.mp4 "https://example.com/video.mp4"
# Resume download
curl -C - -o video.mp4 "https://example.com/video.mp4"
3. yt-dlp for Complex Sources
# When MP4 is behind player logic
yt-dlp -f "mp4" "https://example.com/page-with-video"
# Force MP4 format
yt-dlp -f "best[ext=mp4]" "https://example.com/page-with-video"
# Merge video+audio to MP4
yt-dlp -f "bv*+ba/b" --merge-output-format mp4 "https://example.com/page"
4. Browser-Based Download
// Download MP4 from browser
async function downloadMP4(url, filename) {
try {
const response = await fetch(url);
const blob = await response.blob();
// Create download link
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = filename;
a.click();
// Cleanup
URL.revokeObjectURL(a.href);
} catch (error) {
console.error('Download failed:', error);
}
}
// Usage
downloadMP4('https://example.com/video.mp4', 'downloaded_video.mp4');
5. Node.js Download with Progress
const fs = require('fs');
const https = require('https');
function downloadMP4(url, outputPath) {
return new Promise((resolve, reject) => {
const file = fs.createWriteStream(outputPath);
https.get(url, (response) => {
const totalSize = parseInt(response.headers['content-length'], 10);
let downloadedSize = 0;
response.on('data', (chunk) => {
downloadedSize += chunk.length;
const progress = ((downloadedSize / totalSize) * 100).toFixed(2);
process.stdout.write(`\rDownload progress: ${progress}%`);
});
response.pipe(file);
file.on('finish', () => {
file.close();
console.log('\nDownload completed!');
resolve();
});
file.on('error', reject);
}).on('error', reject);
});
}
Progressive Download Detection
1. Range Request Support
// Check if server supports partial content
async function supportsRangeRequests(url) {
const response = await fetch(url, {
method: 'HEAD'
});
return response.headers.get('accept-ranges') === 'bytes' ||
response.headers.get('content-range') !== null;
}
// Download with range requests
async function downloadWithRanges(url, chunkSize = 1024 * 1024) {
const response = await fetch(url, { method: 'HEAD' });
const totalSize = parseInt(response.headers.get('content-length'));
const chunks = [];
for (let start = 0; start < totalSize; start += chunkSize) {
const end = Math.min(start + chunkSize - 1, totalSize - 1);
const chunkResponse = await fetch(url, {
headers: { 'Range': `bytes=${start}-${end}` }
});
const chunk = await chunkResponse.arrayBuffer();
chunks.push(chunk);
console.log(`Downloaded ${end + 1}/${totalSize} bytes`);
}
// Combine chunks
const totalBuffer = new Uint8Array(totalSize);
let offset = 0;
chunks.forEach(chunk => {
totalBuffer.set(new Uint8Array(chunk), offset);
offset += chunk.byteLength;
});
return totalBuffer;
}
Metadata Extraction
1. Basic MP4 Information
// Extract basic MP4 metadata using File API
async function extractMP4Metadata(file) {
const buffer = await file.arrayBuffer();
const view = new DataView(buffer);
let offset = 0;
const boxes = [];
while (offset < buffer.byteLength - 8) {
const size = view.getUint32(offset, false);
const type = String.fromCharCode(
view.getUint8(offset + 4),
view.getUint8(offset + 5),
view.getUint8(offset + 6),
view.getUint8(offset + 7)
);
boxes.push({ type, size, offset });
if (size === 0) break;
offset += size;
}
return boxes;
}
2. Using ffprobe
# Extract detailed metadata
ffprobe -v quiet -print_format json -show_format -show_streams video.mp4
# Get duration only
ffprobe -v quiet -show_entries format=duration -of csv="p=0" video.mp4
# Get resolution
ffprobe -v quiet -select_streams v:0 -show_entries stream=width,height -of csv="s=x:p=0" video.mp4
Container Analysis and Conversion
1. Check MP4 Compatibility
# Check if MP4 is web-compatible
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of csv="p=0" video.mp4
# Check for faststart (moov atom at beginning)
ffprobe -v error -show_entries format=format_name -of csv="p=0" video.mp4
2. Optimize MP4 for Web
# Move moov atom to beginning for streaming
ffmpeg -i input.mp4 -c copy -movflags +faststart output.mp4
# Convert to web-compatible format
ffmpeg -i input.mp4 \
-c:v libx264 -preset medium -crf 23 \
-c:a aac -b:a 128k \
-movflags +faststart \
output.mp4
3. Fragment MP4 (for DASH/HLS)
# Create fragmented MP4
ffmpeg -i input.mp4 -c copy -f mp4 -movflags frag_keyframe+empty_moov output.mp4
Advanced Detection Techniques
1. Progressive Web App Integration
// Service Worker to intercept MP4 requests
self.addEventListener('fetch', event => {
const url = event.request.url;
if (url.includes('.mp4') || event.request.headers.get('accept')?.includes('video/mp4')) {
console.log('MP4 request intercepted:', url);
// You can modify the request or response here
event.respondWith(
fetch(event.request).then(response => {
console.log('MP4 response:', response);
return response;
})
);
}
});
2. Media Source Extension (MSE) Detection
// Detect MP4 being fed to MSE
if ('MediaSource' in window) {
const originalAppendBuffer = SourceBuffer.prototype.appendBuffer;
SourceBuffer.prototype.appendBuffer = function(buffer) {
// Check if buffer contains MP4 data
if (detectMP4Header(buffer)) {
console.log('MP4 data appended to MSE');
}
return originalAppendBuffer.call(this, buffer);
};
}
Common Issues and Solutions
1. CORS Issues
// Proxy approach for CORS-restricted MP4
const proxyUrl = 'https://cors-anywhere.herokuapp.com/';
const mp4Url = 'https://example.com/video.mp4';
fetch(proxyUrl + mp4Url)
.then(response => response.blob())
.then(blob => {
const url = URL.createObjectURL(blob);
// Use the blob URL
});
2. Large File Handling
// Stream large MP4 files
async function streamMP4Download(url) {
const response = await fetch(url);
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
// Process chunk
console.log('Received chunk:', value.length);
}
}
3. Authentication Issues
# Download with authentication
curl -H "Authorization: Bearer TOKEN" \
-o video.mp4 \
"https://api.example.com/video.mp4"
# Using cookies
curl -b cookies.txt \
-o video.mp4 \
"https://example.com/video.mp4"
Platform-Specific Considerations
YouTube
- Often uses DASH segments, but fallback MP4 available
- Requires extraction via yt-dlp
Vimeo
- Progressive MP4 download available for some videos
- HLS/DASH preferred for adaptive streaming
Wistia
- Direct MP4 URLs often available
- Multiple quality variants
Social Media Platforms
- MP4 usually embedded in page data
- May require API access or scraping
Read more
View all posts →Oct 22, 2025
How to Download H.265 HEVC Videos
Standard: ITU-T H.265 / ISO/IEC HEVC Also Known As: HEVC (High Efficiency Video Coding) File Extensions: .h265, .265, .hevc Containers: MP4, MKV, MOV, TS...
Read articleOct 22, 2025
How to Download VP9 Encoded Videos
Developer: Google Standard: VP9 (WebM Project) File Extensions: .vp9, .webm Containers: WebM, MKV MIME Types: video/webm; codecs="vp9"
Read articleOct 25, 2025
How to Download Loom Videos: A Complete Step-by-Step Guide (With Real Examples & Command Cheatsheet)
Step-by-step Loom download guide with yt-dlp covering share links, embeds, separate streams, and ready-to-copy command cheat sheets.
Read article