Skip to content
DeveloperSeptember 10, 20264 min read

MIME Types Explained: What "Content-Type" Actually Tells the Browser

What a MIME type is, where it comes from, why mismatches break downloads and enable XSS — and how to detect the real MIME type of any file, offline, in your browser.

By FernandesLabs

Founder & Lead Developer · Published September 10, 2026

Share:

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:

  1. The extension, not the content, usually decides the declared type. Rename a PNG to .jpg and most servers will label it image/jpeg even though the bytes are pure PNG.
  2. 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

ExtensionMIME type
.htmltext/html
.csstext/css
.js / .mjstext/javascript
.jsonapplication/json
.pdfapplication/pdf
.pngimage/png
.jpgimage/jpeg
.webpimage/webp
.svgimage/svg+xml
.mp4video/mp4
.woff2font/woff2
.zipapplication/zip
unknown binaryapplication/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/html means "execute me." If a server serves user-uploaded files as text/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 as application/octet-stream (or better, from a separate domain) so the browser never interprets them as HTML.
  • X-Content-Type-Options: nosniff tells 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 as text/plain is 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/plain are ignored in nosniff mode. If your CSS suddenly "doesn't load," inspect the Content-Type response header before touching the CSS itself.

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:

  1. Open the MIME Detector and drop in any file.
  2. 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.
  3. 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

  1. Run a key URL through the HTTP Header Checker — is Content-Type correct and is nosniff present?
  2. Drop a representative file into the MIME Detector — does the real content match what the server claims?
  3. 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.

Was this guide helpful?

Anonymous — one tap, no sign-up.

Get new guides in your inbox

One short email when we publish a new guide or tool. No spam, unsubscribe anytime.

We store your email only to send occasional updates. See our privacy policy — no sharing, no spam.