MIME Type and Magic Byte Checker Guide: Verify Real File Types
A file's extension is a promise, not a proof. Rename a program to "photo.jpg" and most systems will still treat it as a photo until something actually looks inside, which is exactly how malicious uploads slip past careless checks. Two better signals exist: the MIME type, which is the label a system assigns to content, such as image/jpeg for a JPEG photo, and the magic bytes, which are the first few bytes of the file itself and act as a fingerprint for its true format. The MIME Type and Magic Byte Checker reads those signals from a file you provide and reports what the file actually appears to be, so an extension that lies can be caught before the file is trusted. It is a format check on the input you supply, not a guarantee that a file is safe: a correctly identified file can still contain harmful content, and a check is one layer among several, not a verdict.
Magic bytes work because most file formats begin with a fixed signature. A JPEG typically begins with the bytes FF D8 FF, a PNG begins with 89 50 4E 47, which spells ".PNG" after the first byte, a PDF begins with the characters "%PDF", and a ZIP archive begins with "PK". A checker reads those opening bytes and matches them against known signatures, then compares the result with the extension and with the MIME type the file claims. When all three agree, the file is what it says it is, at least in format. When they disagree, something deserves attention: a file claiming to be a PNG but starting with JPEG bytes may simply have been renamed by a confused user, or it may be a deliberate attempt to bypass an upload filter, and the distinction matters for what you do next.
The MIME type itself has two sources that are often confused. One is the type a browser or server declares when sending a file, which comes from configuration and can be wrong or manipulated. The other is the type inferred from the content, which is what a magic-byte check provides. For uploads, the content-derived type is the one to trust, because the declared type is supplied by the uploader's side and can say anything. A robust upload check therefore does three things: it reads the magic bytes to identify the real format, it allows only formats on an explicit list rather than blocking a list of known bad ones, and it treats the file according to its real type, never according to its extension. Even then, files should be stored outside the web root or served with safe headers, because identification is not sanitization.
Worked example
Take a sample check, with values clearly labelled as an illustration. A user uploads a file named "invoice.pdf". The checker reads the first bytes and finds 25 50 44 46, which are the characters "%PDF", the signature of a genuine PDF, and the content-derived MIME type is application/pdf, which matches both the extension and the declared type. The file passes the format check. A second upload is named "avatar.png", but the checker reads the first bytes as FF D8 FF, the JPEG signature, and the content-derived type is image/jpeg, which contradicts the .png extension. The mismatch is flagged, and the file is rejected or quarantined for review rather than stored as a PNG. A third upload is named "report.docx", and the checker reads "PK" at the start, the ZIP signature. That is actually expected, because modern Word documents are ZIP archives containing XML parts, so the content type is application/vnd.openxmlformats-officedocument.wordprocessingml.document, which matches the extension. The lesson of the third case is that a signature alone is not the whole story: some formats share signatures, and the checker's mapping from signature to format must understand container formats, not just single-format signatures. In all three cases, the check took seconds and answered a question the extension could not.
Mistakes to avoid
The first mistake is trusting the extension alone, which is the easiest signal to fake. The second is trusting the declared MIME type from an upload, which is supplied by the sender's side and can be set to anything. The third is using a blocklist of forbidden types instead of an allowlist of permitted ones, which leaves every new or obscure format open by default. The fourth is treating a passing format check as a safety verdict: a genuine image can still carry embedded scripts or malicious metadata, so format identification should sit alongside size limits, content scanning, and safe serving. The fifth is pasting or uploading files that contain secrets or private data into a checker without thinking; a file's content is its content, and sensitive files should be checked in a controlled environment rather than passed around casually.
Putting it into practice
If you accept uploads, add a magic-byte check that enforces an allowlist, and log mismatches so repeated attempts become visible. If you handle files yourself, check any file whose origin you do not know before opening it in a program that might act on its contents. For related tools, the File Type and Magic Byte Detector performs a similar detection, the File Checksum Verifier confirms a file has not changed since it was recorded, and the companion guide on the File Type and Magic Byte Detector explains signature detection in depth. Extensions are labels, MIME types are claims, and magic bytes are evidence; when they disagree, believe the evidence.
Key points
- A file extension is a label that can be renamed, while magic bytes are the file's own opening signature
- Trust the content-derived type over the declared MIME type, since the declared type comes from the sender's side
- Enforce an allowlist of permitted formats for uploads rather than a blocklist of forbidden ones
- A passing format check identifies a file's type but does not prove it is safe, so pair it with other controls
In short: read the first bytes, compare them with the extension and the declared type, allow only formats you expect, and never let a label overrule evidence.