A little help goes a long way. Find a tool/

Developer FIELD NOTES · 3 MIN READ

MIME Types Explained: The Labels Behind Every Download

How Content-Type labels work, why extensions lie, and what octet-stream, sniffing and nosniff mean.

A file lands in your browser and, instead of opening, it drops into the downloads folder. Nothing is corrupt — the bytes are perfect. What failed is a two-line label the server sent before the bytes: the MIME type. Understanding that one label explains most "why won't this open" mysteries on the web.

The two-part label

Every HTTP response carries a Content-Type header, and its value is a media type written type/subtype: image/png says "a PNG image", text/html says "an HTML document", application/pdf says "hand me to a PDF viewer". The first half is the family — text, image, audio, video, application, font — and the second half names the exact format. The official registry is kept by IANA and lists thousands of entries, including vendor-specific types like Photoshop documents; in practice, a few dozen types cover nearly all everyday traffic, which is why a compact MIME Type Lookup is enough for daily work.

Extensions lie; types decide

The filename's extension is only a hint, and a weak one: renaming virus.exe to kitten.png changes nothing about the bytes. Well-behaved servers derive the type from configuration or content, then declare it — and browsers mostly trust the declaration. When the type is missing or generic, browsers may sniff the first bytes and guess. That guessing is a safety net and an attack surface at once: an uploaded "image" that sniffs as HTML can execute scripts in your site's origin. The X-Content-Type-Options: nosniff header disables the guessing, which turns accurate Content-Type headers from politeness into a security requirement.

The families you actually meet

text/* is for human-readable formats and may carry a charset parameter — text/html; charset=utf-8. image, audio and video types cover media, with containers complicating the picture: one extension can legally hold different payloads, so .webm is video/webm for footage and audio/webm for sound, and the label must match the actual content. application/* is the workhorse for everything not directly human-readable — JSON, PDF, ZIP, Word documents — and it owns the famous fallback application/octet-stream, "a stream of bytes", which browsers refuse to render and therefore download. font/* arrived late; fonts spent years masquerading as application types.

Gotchas worth knowing

  • JavaScript is text/javascript as of RFC 9239 (2022). The older application/javascript still works but is legacy, and modules refuse to execute without a proper JavaScript type.
  • HTML sent as text/plain renders as source code — the browser believes the label, not your intentions.
  • octet-stream downloads: the catch-all type is correct only when nothing more specific applies; misusing it is the top cause of "it downloads instead of opening".
  • Unregistered survivors: image/x-icon for favicons and several x- types were never officially registered but won by adoption; they are flagged as such in good reference tables.
  • One type, many extensions: image/jpeg owns both .jpg and .jpeg; video/mpeg owns .mpg and .mpeg. Search by type and you get every sibling back.

Debugging a download in one minute

Open the browser's network panel, click the request, and read the response's Content-Type. If it says octet-stream or text/plain for something that should render, the server mapping is wrong — fix the type, not the browser. When serving user uploads, prefer the type recorded at upload time over the extension at download time, because the extension is whatever the uploader's laptop felt like. And if a type is genuinely unknown, octet-stream is the honest answer — it just should not be the default answer.

Try it yourself

Type pdf, .png or image/png into the MIME Type Lookup and read the category and note for each match; try webm to see one extension carrying two legal types. Then see how Base64 encoding produces data: URIs that carry their own MIME label inline, or how HTTP status codes describe the other half of every response.

Frequently asked questions

What does a MIME type actually do?
It is the label a server attaches to a response or file so the receiving program knows how to treat it: text/html renders as a page, image/png renders as a picture, application/pdf hands off to a viewer. The label travels in the HTTP Content-Type header, and getting it right is the difference between a file that opens and one that downloads.
Why does my file download instead of opening in the browser?
Almost always because the server sent the wrong or generic type — usually application/octet-stream, the "stream of bytes" fallback browsers do not render. Fix the Content-Type (for example image/png for a PNG) and the browser will display it. The generic type is the correct choice only for files that genuinely have no more specific type.
Is a file extension part of the MIME type?
No. The extension is an operating-system naming convention; the MIME type is what travels with the content. They usually agree, but anyone can rename a file, and registries map one extension to several types (WebM carries both audio and video). Servers should decide the type from configuration or content sniffing — never from the filename alone.
What is MIME sniffing and nosniff?
Sniffing is when a browser ignores the declared type and inspects the bytes to guess what a file really is — a safety net for mislabelled content, but also an attack surface, because an image upload can be sniffed as HTML and executed. The X-Content-Type-Options: nosniff header tells the browser to trust the declared type only, which is why accurate Content-Type headers matter for security too.
Which MIME type should modern servers send for JavaScript?
text/javascript. RFC 9239 registered it in 2022 as the canonical type, retiring the older application/javascript spelling. Modules will not execute at all without a JavaScript type, so scripts served as text/plain or octet-stream fail — one of the most common misconfigurations this kind of lookup exists to catch.