Learning & reference

MIME types: the right Content-Type for every file

The Content-Type header decides whether a browser renders a file, downloads it, or refuses it outright. Here is the correct type for every common extension — and the mistakes that quietly break things.

What a MIME type actually controls

The Content-Type header decides whether the browser renders a file, downloads it, or refuses it. Get it wrong and a stylesheet is ignored, a script is blocked, or a PDF downloads instead of opening.

Render vs. download

application/octet-stream (or Content-Disposition: attachment) forces a download. A known type like application/pdf renders inline.

nosniff changes everything

With X-Content-Type-Options: nosniff the browser stops guessing. A stylesheet served as text/plain is then rejected outright rather than silently working.

It is client-supplied on upload

The Content-Type on a multipart upload comes from the browser and can be set to anything. Validate with a signature check, not this header.

Common types by extension

ExtensionMIME typeNotes
.txttext/plainAdd ; charset=utf-8 or browsers guess the encoding.
.html .htmtext/html
.csstext/cssServed as anything else, browsers refuse to apply it.
.js .mjstext/javascriptThe standard type. application/javascript is obsolete but still accepted.
.jsonapplication/jsonNo charset parameter - JSON is always UTF-8.
.xmlapplication/xmltext/xml is legacy and treats it as text.
.csvtext/csvExcel often mislabels these as application/vnd.ms-excel.
.pdfapplication/pdf
.pngimage/png
.jpg .jpegimage/jpegNote: not image/jpg - that type does not exist.
.gifimage/gif
.webpimage/webp
.svgimage/svg+xmlCan contain scripts - never serve user SVG from your main origin.
.icoimage/x-iconimage/vnd.microsoft.icon is the registered name.
.zipapplication/zip
.gzapplication/gzipNot Content-Encoding: gzip - that is a different thing.
.tarapplication/x-tar
.7zapplication/x-7z-compressed
.mp3audio/mpegNot audio/mp3.
.wavaudio/wav
.mp4video/mp4
.webmvideo/webm
.wofffont/woffModern types are font/*; older ones used application/font-woff.
.woff2font/woff2
.ttffont/ttf
.otffont/otf
.docxapplication/vnd.openxmlformats-officedocument.wordprocessingml.documentThe long OOXML types are a classic source of typos.
.xlsxapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet
.pptxapplication/vnd.openxmlformats-officedocument.presentationml.presentation
.docapplication/mswordLegacy binary Office.
.xlsapplication/vnd.ms-excel
.odtapplication/vnd.oasis.opendocument.text
.epubapplication/epub+zip
.wasmapplication/wasmMust be exact or streaming compilation fails.
(unknown)application/octet-streamThe safe default. Triggers a download rather than inline display.

The mistakes that bite

image/jpg

Does not exist. The registered type is image/jpeg; image/jpg is silently accepted by some stacks and rejected by others.

Missing charset

text/html without ; charset=utf-8 leaves the encoding to the browser - accented characters turn into mojibake.

gzip confusion

A .gz file is application/gzip content. Content-Encoding: gzip means "this response was compressed in transit" - set both and the client decompresses once too often.

SVG is executable

SVG can carry <script>. Serving user-uploaded SVG as image/svg+xml from your own origin is stored XSS.

CSV vs Excel

Excel labels CSV exports application/vnd.ms-excel. An importer that only accepts text/csv rejects a perfectly valid file.

OOXML typos

The Office types are ~70 characters long. One wrong character and the download is treated as an unknown binary.

See it live

The generator echoes any content type you ask for, so you can watch how a browser reacts.

Open the generator File signatures →