A download link can lie. I learned that the hard way while building ramrom.io, my little video downloader. A provider would return a 200 status, a filename ending in .mp4, and a body that was actually an HTML error page. The visitor's browser would save it happily, and only when they tried to play it would they find out it was not a video at all.
The extension means nothing. The status code means very little either. So before my proxy hands a file to a visitor, it checks what the file actually is. Here is the set of checks I ended up with, in the order I run them.
1. Do not trust the headers alone
The first check is the Content-Type header, but only as a hint. A real MP4 usually arrives as video/mp4, and an error page usually arrives as text/html. That catches the lazy cases. But headers are set by the same server that served the wrong body, so I never stop there. A provider that returns an HTML error with a video/mp4 header is rare, but a provider that returns a video with a generic application/octet-stream header is common.
2. Read the first bytes before sending anything to the visitor
This is the check that matters. Every MP4 file starts with a box structure, and near the very start, at bytes 4 to 7, you will find the letters ftyp. The first four bytes are the size of that box, then comes ftyp, then a brand name like isom or mp42. An HTML page, by contrast, starts with something like <!DOCTYPE or <html.
So my proxy reads the first chunk of the response into a buffer before it sends any headers to the visitor. If those bytes spell out HTML, I stop, throw the chunk away, and show an honest error instead: the file could not be fetched. If they spell ftyp, I carry on.
Buffering that first chunk matters for a second reason. Once you have sent a Content-Disposition: attachment header and a 200 status to the visitor's browser, you cannot take them back. If you discover the error halfway through, the visitor already has a broken file. Checking first means the failure happens on my side, before the download starts.
3. Sanity-check the size
A real video is rarely a few hundred bytes. If the Content-Length header says 412 bytes and the file claims to be a video, something is wrong. I treat anything absurdly small as suspicious and refuse it, even if the magic bytes look right. The same goes the other way: if the header promises ten megabytes and the connection closes after fifty kilobytes, that is a truncated file, not a finished download, and I say so rather than serving a file that stops mid-sentence.
4. Check the tail only when it is cheap
A full MP4 also contains a moov box with the timing and index data, but hunting for it means reading the whole file, which defeats the point of streaming it straight through. On shared hosting, with no spare memory, that is a bad trade. So I do not parse the whole file. The ftyp check plus the size check catch the real-world failures: error pages, login walls, and expired links that return a pretty HTML page instead of a file.
5. Say what went wrong, in plain words
The last part is not technical at all. When a check fails, the visitor sees a message like "the provider returned an error page instead of a video" rather than a spinner that never ends or a broken file. An honest error is a feature, not an embarrassment.
None of this is clever. It is four small checks, in plain PHP, with no libraries: read the header, read the first bytes, check the size, and fail loudly when something does not add up. But it is the difference between a tool people trust and a tool that hands them a file called video.mp4 that opens as a web page. The filename is a promise. Checking the bytes is how I keep it.
