What a MIME type actually is
MIME stands for Multipurpose Internet Mail Extensions — a standard born for email attachments in the early 1990s that became the way the entire web describes file formats. Every HTTP response carries one in its Content-Type header:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
A MIME type has two parts separated by a slash:
- A type — the broad category:
text,image,audio,video,application,font,model. - A subtype — the specific format:
html,png,json,pdf,svg+xml…
Optional parameters follow after a semicolon, like charset=utf-8 or boundary=... for multipart forms. So text/html; charset=utf-8 reads as: "this is an HTML document, encoded in UTF-8."
Where the browser gets a file's MIME type
Here is the part that surprises people: the MIME type is whatever the server says it is — it is not derived from the file. When you upload photo.jpg to a static host, the server looks up the .jpg extension in a config table and confidently declares image/jpeg. Two consequences:
- The extension, not the content, usually decides the declared type. Rename a PNG to
.jpgand most servers will label itimage/jpegeven though the bytes are pure PNG. - Misconfigured servers lie accidentally. A server without an SVG mapping may serve an SVG as
application/octet-stream("unknown binary"), forcing a download instead of rendering.
Common MIME types worth memorizing
| Extension | MIME type |
|---|---|
.html | text/html |
.css | text/css |
.js / .mjs | text/javascript |
.json | application/json |
.pdf | application/pdf |
.png | image/png |
.jpg | image/jpeg |
.webp | image/webp |
.svg | image/svg+xml |
.mp4 | video/mp4 |
.woff2 | font/woff2 |
.zip | application/zip |
| unknown binary | application/octet-stream |
Note the historical baggage: plain text/javascript is the modern standard, but older servers still emit application/javascript — both work in browsers today.
Why MIME mismatches are dangerous
Browsers trust Content-Type for security-critical decisions:
text/htmlmeans "execute me." If a server serves user-uploaded files astext/html, an attacker can upload a "profile picture" that is actually an HTML page with scripts — and it will run on your origin, a classic stored-XSS vector. The fix is serving uploads asapplication/octet-stream(or better, from a separate domain) so the browser never interprets them as HTML.X-Content-Type-Options: nosnifftells the browser: do not second-guess the declared type. Without it, browsers "MIME sniff" the actual bytes and may execute a mislabeled script anyway. With it, a script served astext/plainis blocked outright — which is exactly why the header stops the attack, and also why a misconfigured server that labels JavaScript as plain text will find its scripts refused by modern browsers.- Strict MIME checking breaks sloppy servers. Stylesheets served as
text/plainare ignored in nosniff mode. If your CSS suddenly "doesn't load," inspect theContent-Typeresponse header before touching the CSS itself.
Sponsored
How to check a file's real MIME type — offline
Because the declared type comes from the server, the interesting question is usually what the file really is, based on its content. That is determined by the file's binary signature (magic bytes), which is exactly what the MIME Detector reads:
- Open the MIME Detector and drop in any file.
- It reads the first bytes of the file locally — the file never leaves your browser — and reports the detected MIME type and the matching extension.
- Compare the detected type with what your server declares. Mismatch? Fix the server mapping or re-export the file.
For deeper verification, combine it with the File Signature Inspector (shows the raw magic bytes) and the HTTP Header Checker (shows the Content-Type your server actually sends for a URL).
Fixing MIME problems on your server
Nginx — check mime.types is included and add anything missing:
types {
text/javascript js mjs;
image/webp webp;
image/svg+xml svg svgz;
font/woff2 woff2;
}
# And enforce nosniff globally:
add_header X-Content-Type-Options nosniff always;
Apache — mod_mime maps extensions, and headers go in .htaccess:
AddType image/webp .webp
AddType font/woff2 .woff2
AddType image/svg+xml .svg .svgz
Header always set X-Content-Type-Options nosniff
Object storage (S3, R2, etc.) — set the ContentType metadata at upload time; the SDK will not guess it for you.
The 60-second audit
- Run a key URL through the HTTP Header Checker — is
Content-Typecorrect and isnosniffpresent? - Drop a representative file into the MIME Detector — does the real content match what the server claims?
- Check user-upload handling: are uploads ever served as
text/html? If yes, fix that today.
MIME types look like plumbing, but they decide whether a file renders, downloads, or executes. Ten minutes of checking is cheaper than one security incident.
Related free tools
Try these free online tools — all run in your browser with no sign-up.
Keep reading
More hand-written guides from the blog.